簡體   English   中英

C++ 中的線性搜索與二分搜索實時性能

[英]Linear search vs binary search real time performance in 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, int s, int e, 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, 0, 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, 0, m - 1, 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";
}

編譯沒有優化,得到以下 output -

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

當使用 -O3 優化編譯時,得到這個 output -

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

我知道對於小數組大小,二進制搜索可能比線性搜索要昂貴,但無法通過添加 -O3 來理解這種幅度差異的原因

編譯器設法意識到您的線性搜索是一個 noop(它沒有副作用)並將其轉換為什么都不做。 所以它需要零時間。

要解決此問題,請考慮獲取返回值並將其相加,然后將其打印在計時塊之外。

我用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, int s, int e, 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, 0, m - 1, key);
    benchmark::DoNotOptimize(result);
  }
}
BENCHMARK(Linear);

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

結果:

在此處輸入圖像描述

僅對for (auto _: state) {內部的代碼進行了基准測試。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM