2011-12-23 164 views
22

我只試圖在C++ 11比較lambda表達式的性能,所以我也測試 - 元素的計算總和中double值的向量。下面是執行:爲什麼C++ lambda比多次調用時的普通函數慢?

#include <vector> 
#include <algorithm> 
#include <iostream> 
#include <ctime> 

#define LOG(x) { std::cout << #x << " = " << (x) << "\n"; } 
#define TIME(t) { std::cout << ((double)(clock() - (t))/CLOCKS_PER_SEC) << " s\n"; } 

double sum(const std::vector<double>& v) 
{ 
    double s = 0.0; 
    for (auto i = v.cbegin(); i != v.cend(); ++i) 
     s += *i; 
    return s; 
} 

int main() 
{ 
    const size_t MAX = 1; // number of tests 
    const size_t SIZE = 100000000; // length of the vector 

    std::vector<double> v(SIZE, 1.0); 
    double out; 

    clock_t clk; 

    std::cout << "iterator\n"; 

    clk = clock(); 
    out = 0.0; 
    for (size_t i = 0; i < MAX; ++i) 
     out += sum(v); 
    TIME(clk) 
    LOG(out) 

    std::cout << "\nlambda\n"; 

    clk = clock(); 
    out = 0.0; 
    for (size_t i = 0; i < MAX; ++i) 
     std::for_each(v.cbegin(), v.cend(), [&](double d) { out += d; }); 
    TIME(clk) 
    LOG(out) 

    return 0; 
} 

下面是這個程序的結果(在VS2010 SP1編譯,在Release模式):

 
iterator 
0.32 s 
out = 1e+008 

lambda 
0.326 s 
out = 1e+008 

正如人們可以看到,在性能上幾乎沒有差別。然而,如果我給10作爲MAX的值(這意味着求和將被執行10次,而不是一個),結果不同:

 
iterator 
0.287 s 
out = 1e+009 

lambda 
2.84 s 
out = 1e+009 

試驗lambda表達式花了大約10倍更多的時間。爲什麼?我認爲它可以通過這樣的事實造成的,即在每次迭代新拉姆達被創建,但磨我嘗試這樣做:

out = 0.0; 
auto f = [&](double d) { out += d; }; 
for (size_t i = 0; i < MAX; ++i) 
    std::for_each(v.cbegin(), v.cend(), f); 

結果並沒有改變。有人可以向我解釋這種行爲嗎?

+2

這非常有趣!你可以嘗試在手寫循環中使用lambda而不是'foreach'嗎? – dasblinkenlight 2011-12-23 02:54:30

+0

g ++ 4.6.2在Linux上給出了完全相同的運行時間(在我的電腦上爲0.13 - 0.12秒) – Cubbi 2011-12-23 03:12:31

+0

沒有更多的神祕感,請檢查我的編輯。我的錯誤,但我仍然覺得它很有趣。 :) – Archie 2011-12-23 03:12:51

回答

39

事實證明,這與lambda表達式沒有任何問題,只是編譯器通過緩存sum()函數的結果優化了第一種情況下的外部循環。在將第一種情況更改爲這種形式之後:

out = 0.0; 
for (size_t i = 0; i < MAX; ++i) 
{ 
    out += sum(v); 
    v[i] = 1.0; // this adds O(1) time and prevents caching 
} 

兩種情況下的時間都大致相等,以lambda作爲最愛。

+9

很好的調查。 – 2011-12-23 03:30:24

+3

故事的寓意 - 總是用*真實*代碼來測試和測試,而不是*玩具*代碼。 – 2011-12-28 01:14:15

+2

@Archie您是否還將v [i] = 1.0添加到lambda中? – sprite 2013-12-30 05:35:25

相關問題