微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

C++中的线性搜索与二分搜索实时性能

如何解决C++中的线性搜索与二分搜索实时性能

使用以下代码比较二进制搜索与线性搜索在 C++ 中的实时性能时获得完全出乎意料的结果 -

typedef std::chrono::microseconds us;

int linear_search(uint64_t* val,int s,int e,uint64_t k) {
    while (s < e) {
      if (!less<uint64_t>()(val[s],k)) {
        break;
      }
      ++s;
    }
    return {s};
}

int binary_search(uint64_t* val,uint64_t k) {
    while (s != e) {
      const int mid = (s + e) >> 1;
      if (less<uint64_t>()(val[mid],k)) {
        s = mid + 1;
      } else {
        e = mid;
      }
    }
    return {s};
}


int main() {

    // Preparing data
    int iter = 1000000;
    int m = 1000;
    uint64_t val[m];
    for(int i = 0; i < m;i++) {
        val[i] = rand();
    }
    sort(val,val + m);
    uint64_t key = rand();

    // Linear search time computation
    auto start = std::chrono::system_clock::Now();
    for (int i = 0; i < iter; i++) {
        linear_search(val,m - 1,key);
    }
    auto end = std::chrono::system_clock::Now();
    auto elapsed_us = std::chrono::duration_cast<us>(end - start);
    std::cout << "Linear search: " << m << " values "
              << elapsed_us.count() << "us\n";

    // Binary search time computation
    start = std::chrono::system_clock::Now();
    for (int i = 0; i < iter; i++) {
        binary_search(val,key);
    }
    end = std::chrono::system_clock::Now();
    elapsed_us = std::chrono::duration_cast<us>(end - start);
    std::cout << "Binary search: " << m <<" values "
              << elapsed_us.count() << "us\n";
}

未优化编译,得到如下输出 -

Linear search: 1000 values 1848621us
Binary search: 1000 values 24975us

当使用 -O3 优化编译时,得到这个输出 -

Linear search: 1000 values 0us
Binary search: 1000 values 13424us

我知道对于小数组大小,二进制搜索可能比线性搜索昂贵,但无法通过添加 -O3 来理解这种差异的原因

解决方法

我使用 https://quick-bench.com 对您的代码进行了基准测试,二进制搜索要快得多(对于 m = 100,它在 m = 1000 处中断)。这是我的基准代码:

int linear_search(uint64_t* val,int s,int e,uint64_t k) {
    while (s < e) {
      if (!std::less<uint64_t>()(val[s],k)) {
        break;
      }
      ++s;
    }
    return s;
}

int binary_search(uint64_t* val,uint64_t k) {
    while (s != e) {
      const int mid = (s + e) >> 1;
      if (std::less<uint64_t>()(val[mid],k)) {
        s = mid + 1;
      } else {
        e = mid;
      }
    }
    return s;
}

constexpr int m = 100;
uint64_t val[m];
uint64_t key = rand();
void init() {
  static bool isInitialized = false;
  if (isInitialized) return;
  for(int i = 0; i < m;i++) {
    val[i] = rand();
  }
  std::sort(val,val + m);
  isInitialized = true;
}

static void Linear(benchmark::State& state) {
  init();
  for (auto _ : state) {
    int result = linear_search(val,m - 1,key);
    benchmark::DoNotOptimize(result);
  }
}
BENCHMARK(Linear);

static void Binary(benchmark::State& state) {
  init();
  for (auto _ : state) {
    int result = binary_search(val,key);
    benchmark::DoNotOptimize(result);
  }
}
BENCHMARK(Binary);

结果:

enter image description here

仅对 for (auto _ : state) { 中的代码进行了基准测试。

,

编译器设法意识到您的线性搜索是一个空操作(它没有副作用)并将其转换为什么都不做。所以它需要零时间。

要解决这个问题,请考虑获取返回值并将其相加,然后将其打印到计时块之外。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。