我很快写了一个“简单”的文章,但希望它不要太愚蠢,以免
总是尝试不为std::function
分配lambda的方法(因为它比较慢?->至少有一个虚函数(不确定))很有意义。
#include <iostream>
#include <functional>
#include <chrono>
typedef std::chrono::high_resolution_clock::time_point TimeVar;
#define duration(a) std::chrono::duration_cast<std::chrono::nanoseconds>(a).count()
#define timeNow() std::chrono::high_resolution_clock::now()
template<typename T, typename F>
auto time(T t, F &&rF)
{
std::cout << t << "\t";
TimeVar t1=timeNow();
int a = rand()%10;
for(int i=0;i<10000000;i++)
{
a = rF(a);
}
auto count = duration(timeNow()-t1);
std::cout << "a: " << a << " time: " << count << " ns " << std::endl;
return count;
}
template<typename T>
auto timeN(T t)
{
std::cout << t << "\t";
TimeVar t1=timeNow();
int a = rand()%10;
for(int i=0;i<10000000;i++)
{
a = a + rand()%10;
}
auto count = duration(timeNow()-t1);
std::cout << "a: " << a << " time: " << count << " ns " << std::endl;
return count;
}
int main()
{
auto c1 = time("lambda: ", [](int a) { return a + rand()%10; });
auto c2 = time("std::function: ", std::function<int(int)>{[](int a) { return a + rand()%10; }});
auto c3 = timeN("baseline: ");
std::cout << std::endl;
std::cout << "lambda: \t" << (float)c1/c3 << " x slower then baseline" << std::endl;
std::cout << "std::function: \t" << (float)c2/c3 << " x slower then baseline" << std::endl;
std::cout << "std::function: \t" << (float)c2/c1 << " x slower then lambda" << std::endl;
}
输出:
lambda: a: 45011713 time: 182743890 ns
std::function: a: 45000320 time: 161290160 ns
baseline: a: 45004251 time: 134701347 ns
lambda: 1.35666 x slower then baseline
std::function: 1.19739 x slower then baseline
std::function: 0.882602 x slower then lambda
这让我感到困惑,因为lambda比std :: function慢。为什么?我的意思是lambda的类型是编译器生成的,并且我认为它可以优化更多,而不是不透明的std :: function类型。 (如果使用clang进行编译,则会得到相反的结果)。 问题还出了,如果std :: function是不透明的类型,为什么它会这么快?分配类型对lambda来说是特殊的并且已优化吗?
答案 0 :(得分:4)
启用优化并没有太大区别:
~$ g++ -O3 --std=c++14 a.cpp
~$ ./a.out
lambda: a: 45002817 time: 63951040 ns
std::function: a: 45002682 time: 64764776 ns
baseline: a: 44990972 time: 62371825 ns
lambda: 1.02532 x slower then baseline
std::function: 1.03837 x slower then baseline
std::function: 1.01272 x slower then lambda
~$ ./a.out
lambda: a: 45002817 time: 63315194 ns
std::function: a: 45002682 time: 63703902 ns
baseline: a: 44990972 time: 64156841 ns
lambda: 0.986881 x slower then baseline
std::function: 0.99294 x slower then baseline
std::function: 1.00614 x slower then lambda
~$ ./a.out
lambda: a: 45002817 time: 64336198 ns
std::function: a: 45002682 time: 64334809 ns
baseline: a: 44990972 time: 62341043 ns
lambda: 1.032 x slower then baseline
std::function: 1.03198 x slower then baseline
std::function: 0.999978 x slower then lambda
~$ ./a.out
lambda: a: 45002817 time: 64270878 ns
std::function: a: 45002682 time: 63267123 ns
baseline: a: 44990972 time: 62374261 ns
lambda: 1.03041 x slower then baseline
std::function: 1.01431 x slower then baseline
std::function: 0.984382 x slower then lambda
~$ ./a.out
lambda: a: 45002817 time: 63049074 ns
std::function: a: 45002682 time: 65208456 ns
baseline: a: 44990972 time: 62404926 ns
lambda: 1.01032 x slower then baseline
std::function: 1.04492 x slower then baseline
std::function: 1.03425 x slower then lambda
~$ ./a.out
lambda: a: 45002817 time: 67177288 ns
std::function: a: 45002682 time: 65373651 ns
baseline: a: 44990972 time: 63936167 ns
lambda: 1.05069 x slower then baseline
std::function: 1.02248 x slower then baseline
std::function: 0.973151 x slower then lambda