我想为一些函数的执行计时,我给自己写了一个助手:
using namespace std;
template<int N = 1, class Fun, class... Args>
void timeExec(string name, Fun fun, Args... args) {
auto start = chrono::steady_clock::now();
for(int i = 0; i < N; ++i) {
fun(args...);
}
auto end = chrono::steady_clock::now();
auto diff = end - start;
cout << name << ": "<< chrono::duration<double, milli>(diff).count() << " ms. << endl;
}
我认为以这种方式为成员函数计时,我必须使用 bind 或 lambda,我想看看哪个对性能的影响较小,所以我这样做了:
const int TIMES = 10000;
timeExec<TIMES>("Bind evaluation", bind(&decltype(result)::eval, &result));
timeExec<1>("Lambda evaluation", [&]() {
for(int i = 0; i < TIMES; ++i) {
result.eval();
}
});
结果是:
Bind evaluation: 0.355158 ms.
Lambda evaluation: 0.014414 ms.
我不知道内部原理,但我认为 lambda 不可能比 bind 更好。我能想到的唯一合理的解释是编译器优化了 lambda 循环中的后续函数评估。
你会怎么解释?
最佳答案
I assume that lambda cannot be that better than bind.
这是一个相当成见。
Lambda 被绑定(bind)到编译器内部,因此可以找到额外的优化机会。此外,它们旨在避免效率低下。
但是,这里可能没有发生编译器优化技巧。可能的罪魁祸首是 bind 的参数 bind(&decltype(result)::eval, &result)
。您正在传递一个指向成员函数 (PTMF) 的指针和一个对象。与 lambda 类型不同,PTMF 不捕获实际调用的函数;它只包含函数签名(参数和返回类型)。慢循环使用的是间接分支函数调用,因为编译器无法通过常量传播解析函数指针。
如果将成员 eval()
重命名为 operator () ()
并去掉 bind
,那么显式对象本质上将表现得像 lambda,性能差异应该消失。
关于c++ - std::bind 与 lambda 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24852764/