为什么C++11的lambda演算速度比用functor还要慢?该怎么解决
为什么C++11的lambda演算速度比用functor还要慢?
我想对比一下lambda演算的性能,和以前自己写一个functor的时候的性能。哪一个更高。
自己写一个functor来调用类的函数,需要我在functor构造的时候把类函数地址和参数地址都存下来,然后operator()的时候再调用类对象。这样会产生一个开销,就是要存储这些参数,然后按照指针的方式来调用。
functor用了1281ms
lambda用了1328ms
可是我发现用lambda演算的时候,时间需要的更长。VC2010 sp1编译,代码如下。
这是为什么呢?
------解决方案--------------------
直接用你的代码测试,结果基本还是一样.lambda版本要比functor快.因为你这个functor用了成员指针,而lambda中是直接成员调用. 只有icl版本,lambda稍慢于functor.
其实,lambda还能更快的.比如你这里的capture是[&],如果改成[=],在vc11和icl下,lambda的性能会提升一大截.
[&]捕获的局部变量是通过引用,也就是通过成员地址,对于只读的整型来说,这样意义不大,会带来间接访问的开销.而[=]则是值捕获,效果和在functor中使用成员保存局部变量相当.
不过vc10对volatile变量的值捕获支持有BUG...代码编译不通过.
我想对比一下lambda演算的性能,和以前自己写一个functor的时候的性能。哪一个更高。
自己写一个functor来调用类的函数,需要我在functor构造的时候把类函数地址和参数地址都存下来,然后operator()的时候再调用类对象。这样会产生一个开销,就是要存储这些参数,然后按照指针的方式来调用。
functor用了1281ms
lambda用了1328ms
可是我发现用lambda演算的时候,时间需要的更长。VC2010 sp1编译,代码如下。
这是为什么呢?
- C/C++ code
#include"stdafx.h" #include<iostream> #include<string> #include<vector> #include<functional> #include<algorithm> #include<Windows.h> using namespace std; template<class C, class T1, class T2> class Pred2Vars{ public: typedef void (C::*PredPtr)( T1, T2 ); Pred2Vars( T1 p1, T2 p2, PredPtr pPred ) : m_p1( p1 ),m_p2( p2 ),m_pPred( pPred ){} void operator()( C* pObject ) { ((*pObject).*m_pPred)( m_p1, m_p2 ); } private: T1 m_p1; T2 m_p2; PredPtr m_pPred; }; struct s{ void f2(int a,int b){ i+=a; i+=b; } void f7(int i1,int i2,int i3,int i4,int i5,int i6,int i7){ i+=i1; i+=i2; i+=i3; i+=i4; i+=i5; i+=i6; i+=i7; } int i; s():i(0){} }; typedef void (s::*psf)(int,int); int main(int argc, char *argv[]) { const int l=100000000; s* ps=new s[l]; vector<s*> vps; for(int i=0;i<l;++i){ ps[i].i=1; vps.push_back(&ps[i]); } volatile int i=2; volatile int j=i+1; { DWORD ret1=GetTickCount(); std::for_each(vps.begin(),vps.end(), Pred2Vars<s,int,int>(i,j,&s::f2)); DWORD ret2=GetTickCount(); printf("%d\n",ret2-ret1); } { DWORD ret1=GetTickCount(); std::for_each(vps.begin(),vps.end(),[&](s* ps){ps->f2(i,j);}); DWORD ret2=GetTickCount(); printf("%d\n",ret2-ret1); } delete[] ps; return EXIT_SUCCESS; }
------解决方案--------------------
直接用你的代码测试,结果基本还是一样.lambda版本要比functor快.因为你这个functor用了成员指针,而lambda中是直接成员调用. 只有icl版本,lambda稍慢于functor.
其实,lambda还能更快的.比如你这里的capture是[&],如果改成[=],在vc11和icl下,lambda的性能会提升一大截.
[&]捕获的局部变量是通过引用,也就是通过成员地址,对于只读的整型来说,这样意义不大,会带来间接访问的开销.而[=]则是值捕获,效果和在functor中使用成员保存局部变量相当.
不过vc10对volatile变量的值捕获支持有BUG...代码编译不通过.