簡體   English   中英

使用-O3或-Ofast來編譯基准代碼還是刪除代碼是否現實?

[英]Is it realistic to use -O3 or -Ofast to compile your benchmark code or will it remove code?

當使用-O3編譯下面的基准代碼時,我對它在延遲方面的差異印象深刻,所以我開始懷疑編譯器是否通過某種方式刪除代碼而“欺騙”。 有沒有辦法檢查? 我可以安全地使用-O3進行基准測試嗎? 期望速度增加15倍是否現實?

沒有-O3結果:平均值: 239納米最小值:230納米(900萬次迭代)
結果-O3 :平均值: 14納米,最小值:12納米(900萬次迭代)

int iterations = stoi(argv[1]);
int load = stoi(argv[2]);

long long x = 0;

for(int i = 0; i < iterations; i++) {

    long start = get_nano_ts(); // START clock

    for(int j = 0; j < load; j++) {
        if (i % 4 == 0) {
            x += (i % 4) * (i % 8);
        } else {
            x -= (i % 16) * (i % 32);
        }
    }

    long end = get_nano_ts(); // STOP clock

    // (omitted for clarity)
}

cout << "My result: " << x << endl;

注意:我使用clock_gettime來衡量:

long get_nano_ts() {
    struct timespec ts;
    clock_gettime(CLOCK_MONOTONIC, &ts);
    return ts.tv_sec * 1000000000 + ts.tv_nsec;
}

在啟用優化編譯時,編譯器肯定會“作弊”並刪除不必要的代碼。 實際上,加速代碼的速度非常快,幾乎總能帶來令人印象深刻的加速。 如果它能以某種方式導出一個公式來計算恆定時間的結果,而不是使用這個循環,它會。 常數因子15並非一帆風順。

但是,這並不意味着你就應該剖析未經優化的構建! 實際上,當使用像C和C ++這樣的語言時,未優化構建的性能幾乎完全沒有意義。 你根本不必擔心。

當然,這可能會干擾上面顯示的微基准測試。 兩點:

  1. 通常,這種微觀優化也無關緊要。 更喜歡分析您的實際程序,然后消除瓶頸。
  2. 如果您真的想要這樣的微基准測試,請依賴於某些運行時輸入並顯示結果。 這樣,編譯器本身無法刪除功能,只需使其速度相當快。

由於您似乎正在這樣做,因此您展示的代碼很有可能成為合理的微觀基准。 你應該注意的一件事是你的編譯器是否同時調用get_nano_ts(); 到循環的同一側。 允許這樣做,因為“運行時間”不算作可觀察到的副作用。 (該標准甚至不要求你的機器以有限的速度運行。) 這里有人認為這通常不是問題,盡管我無法判斷給出的答案是否有效。

如果您的程序沒有做任何其他昂貴的事情,那么您想要進行基准測試(如果可能的話,不應該做任何事情),您也可以將時間測量“移出”,例如隨着時間的推移

對您認為正在測量的內容進行基准測量可能非常困難。 在內循環的情況下:

for (int j = 0;  j < load;  ++j)
        if (i % 4 == 0)
                x += (i % 4) * (i % 8);
        else    x -= (i % 16) * (i % 32);

一個精明的編譯器可能能夠看透並將代碼更改為:

 x = load * 174;   // example only

我知道這不是等價的,但有一些相當簡單的表達式可以取代該循環。

可以肯定的是使用gcc -S編譯器選項並查看它生成的匯編代碼。

您應始終使用已啟用的優化進行基准測試。 但是,確保您想要的時間不會被編譯器優化掉是很重要的。

通過在計時器停止后打印出計算結果來實現此目的的一種方法:

long long x = 0;

for(int i = 0; i < iterations; i++) {

    long start = get_nano_ts(); // START clock

    for(int j = 0; j < load; j++) {
        if (i % 4 == 0) {
            x += (i % 4) * (i % 8);
        } else {
            x -= (i % 16) * (i % 32);
        }
    }

    long end = get_nano_ts(); // STOP clock

    // now print out x so the compiler doesn't just ignore it:
    std::cout << "check: " << x << '\n',

    // (omitted for clarity)
}

當比較幾種不同算法的基准時,這些算法也可以用作檢查每個算法產生相同的結果。

暫無
暫無

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

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