为什么C++ lambda在多次调用时比普通函数慢?

Arc*_*hie 26 c++ performance lambda c++11

我只是试图比较C++ 11中lambda表达式的性能,所以我做了测试 - 计算double值向量中元素的总和.这是实施:

#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;
}
Run Code Online (Sandbox Code Playgroud)

以下是此程序的结果(在VS2010 SP1中,在发布模式下编译):

iterator
0.32 s
out = 1e+008

lambda
0.326 s
out = 1e+008

可以看出,性能几乎没有差异.但是,如果我将10作为值MAX(它表示求和将执行10次而不是1次),结果会有所不同:

iterator
0.287 s
out = 1e+009

lambda
2.84 s
out = 1e+009

对λ表达的测试花费大约10倍的时间.为什么?我认为这可能是由于事实造成的,即每次迭代都会创建新的lambda,但是我试过这个:

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);
Run Code Online (Sandbox Code Playgroud)

结果没有改变.有人可以向我解释这种行为吗?

Arc*_*hie 49

原来,这不是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
}
Run Code Online (Sandbox Code Playgroud)

两个案例的时间大致相等,lambda是最喜欢的.

  • 好的调查. (11认同)
  • 故事的寓意 - 总是用*真正的*代码进行测试和基准测试,从不使用*玩具*代码. (3认同)
  • @Archie您是否也将v [i] = 1.0添加到lambda中? (2认同)