簡體   English   中英

埃拉托色尼 C++ 代碼的篩選在連續運行中加速 - 為什么?

[英]Sieve of eratosthenes c++ code speeds up in consecutive runs - why?

我對這個問題進行了快速檢查,但找不到答案 - 盡管我猜它之前可能已經在這里提出過。

我正在忙着用 C++ 編寫一個簡單的埃拉托色尼篩實現,並為結果計時:

#include <iostream> 
#include <math.h>


int main() {

  int n = 100000;
  int seive [n];

  for (int i=0; i<n; i++) {
    seive[i] = i;
  }

  for (int i=2; i < ceil(sqrt(n)); i++) {
    for (int j=i*2; j<=n; j+=i) {
      seive[j-1] = -9;
    }
  }

  for (int i=0; i<n; i++) {
    if (seive[i] != -9) {
      std::cout << i+1 << "\n";
    }
  }

  return 0;
}

我使用以下方法編譯它:

g++ seive.cpp -o seiveCpp

然后使用它計時:

time ./seiveCpp

第一次:

./seiveCpp  0.01s user 0.01s system 10% cpu 0.184 total

第二次:

./seiveCpp  0.01s user 0.01s system 58% cpu 0.034 total

第三次:

./seiveCpp  0.01s user 0.01s system 59% cpu 0.037 total

等等。

如果我多次重復此操作,似乎第一次運行代碼總是比所有連續時間慢 5 倍左右。

這背后的原因是什么?

我在 2017 款 MacBook Pro、2.3 GHz 雙核 Intel Core i5 上運行它,並使用 Apple clang 版本 11.0.0 (clang-1100.0.33.12

原因是因為分支預測器。 第一次運行時,計算機對程序一無所知,但在執行它時,會在代碼(for 和 if)的跳轉中找到邏輯,然后可以更好地預測它應該采用哪個分支。 在現代處理器中,有很長的命令管道,因此正確預測跳轉可以顯着減少工作時間。

因此,要按執行時間比較幾個算法,最好運行一百次並花費最少的時間。

鑒於非常大的差異,我猜想 CPU 在您開始第一次運行時處於較低的性能模式,但是在第一次運行的負載下,操作系統將其切換到較高的性能模式,您觀察到執行時間降低.

如果您想避免這種影響,請確保您的筆記本電腦連接到交流電源並且禁用所有節能選項。

在任何情況下,仍然會存在緩存效果(例如,可執行文件中的內容可能會緩存在內存中)。 但我認為這些不應該是 100 毫秒的數量級。

一般來說,當您對代碼進行基准測試時,您應該始終進行熱身運行,因為出於某種原因,總會在某種程度上產生這種影響。 可以這么說,您通常希望在環境達到平衡狀態時執行實際測試運行。

當操作系統第一次將文件加載到內存中多次運行程序時,下一次它很可能已經存在(盡管根據編譯器/鏈接器的設置,重定位可能仍然是必要的,即位置無關代碼生成)。 如果您在單個進程中多次運行相同的代碼(這是收集性能數據時的一個好主意 - 將計時代碼放入程序中並多次運行感興趣的代碼),分支位置答案將更有可能適用,為每個循環計時,而不是多次運行整個程序並使用外部時間程序)。

暫無
暫無

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

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