免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 5174 | 回复: 7
打印 上一主题 下一主题

为什么C++11的lambda演算速度比用functor还要慢? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-04-06 10:05 |只看该作者 |倒序浏览
本帖最后由 zuiwei 于 2012-04-06 10:06 编辑

我想对比一下lambda演算的性能,和以前自己写一个functor的时候的性能。哪一个更高。
自己写一个functor来调用类的函数,需要我在functor构造的时候把类函数地址和参数地址都存下来,然后operator()的时候再调用类对象。这样会产生一个开销,就是要存储这些参数,然后按照指针的方式来调用。
functor用了1281ms
lambda用了1328ms

可是我发现用lambda演算的时候,时间需要的更长。VC2010 sp1编译,代码如下。
这是为什么呢?

  1. #include"stdafx.h"
  2. #include<iostream>
  3. #include<string>
  4. #include<vector>
  5. #include<functional>
  6. #include<algorithm>
  7. #include<Windows.h>
  8. using namespace std;
  9. template<class C, class T1, class T2>
  10. class Pred2Vars{
  11. public:
  12.     typedef void (C::*PredPtr)( T1, T2 );

  13.     Pred2Vars( T1 p1, T2 p2, PredPtr pPred ) :
  14.         m_p1( p1 ),m_p2( p2 ),m_pPred( pPred ){}

  15.     void operator()( C* pObject )    {
  16.         ((*pObject).*m_pPred)( m_p1, m_p2 );
  17.     }
  18. private:
  19.     T1 m_p1;
  20.     T2 m_p2;
  21.     PredPtr m_pPred;
  22. };

  23. struct s{
  24.         void f2(int a,int b){
  25.                 i+=a;
  26.                 i+=b;
  27.         }
  28.         void f7(int i1,int i2,int i3,int i4,int i5,int i6,int i7){
  29.                 i+=i1;
  30.                 i+=i2;
  31.                 i+=i3;
  32.                 i+=i4;
  33.                 i+=i5;
  34.                 i+=i6;
  35.                 i+=i7;
  36.         }
  37.         int i;
  38.         s():i(0){}
  39. };
  40. typedef void (s::*psf)(int,int);
  41. int main(int argc, char *argv[])
  42. {
  43.         const int l=100000000;
  44.         s* ps=new s[l];
  45.         vector<s*> vps;
  46.         for(int i=0;i<l;++i){
  47.                 ps[i].i=1;
  48.                 vps.push_back(&ps[i]);
  49.         }
  50.         volatile int i=2;
  51.         volatile int j=i+1;
  52.     {//2605
  53.                 DWORD ret1=GetTickCount();
  54.                 std::for_each(vps.begin(),vps.end(),
  55.                         Pred2Vars<s,int,int>(i,j,&s::f2));
  56.                 DWORD ret2=GetTickCount();
  57.                 printf("%d\n",ret2-ret1);
  58.         }
  59.         {//2574
  60.                 DWORD ret1=GetTickCount();
  61.                 std::for_each(vps.begin(),vps.end(),[&](s* ps){ps->f2(i,j);});
  62.                 DWORD ret2=GetTickCount();
  63.                 printf("%d\n",ret2-ret1);
  64.         }
  65.         delete[] ps;
  66.     return EXIT_SUCCESS;
  67. }
复制代码

论坛徽章:
0
2 [报告]
发表于 2012-04-06 11:48 |只看该作者
我现在是VC2010编译release版开了/O2,我测试了一下7个参数的情况,发现还是functor比lamdba快:
代码如下: functor运行781ms,lambda运行860ms。我交换了运行的顺序,发现结果不变。
这又是为什么呢?

  1. #include"stdafx.h"
  2. #include<iostream>
  3. #include<string>
  4. #include<vector>
  5. #include<functional>
  6. #include<algorithm>
  7. #include<Windows.h>
  8. using namespace std;

  9. template<class C, class T1, class T2, class T3, class T4, class T5, class T6, class T7>class Pred7Var
  10. {
  11. public:
  12.     typedef void (C::*PredPtr)( T1, T2, T3, T4, T5, T6, T7 );

  13.     Pred7Var( T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, PredPtr pPred ) :
  14.     m_p1( p1 ),
  15.         m_p2( p2 ),
  16.         m_p3( p3 ),
  17.         m_p4( p4 ),
  18.         m_p5( p5 ),
  19.         m_p6( p6 ),
  20.         m_p7( p7 ),
  21.         m_pPred( pPred ){}

  22.     void operator()( C* pObject )
  23.     {
  24.         ((*pObject).*m_pPred)( m_p1, m_p2, m_p3, m_p4, m_p5, m_p6, m_p7 );
  25.     }

  26. private:
  27.     T1 m_p1;
  28.     T2 m_p2;
  29.     T3 m_p3;
  30.     T4 m_p4;
  31.     T5 m_p5;
  32.     T6 m_p6;
  33.     T7 m_p7;
  34.     PredPtr m_pPred;
  35. };
  36. struct s{
  37.      void f2(int a,int b){
  38.          i+=a;
  39.          i+=b;
  40.      }
  41.      void f7(int i1,int i2,int i3,int i4,int i5,int i6,int i7){
  42.          i+=i1;
  43.          i+=i2;
  44.          i+=i3;
  45.          i+=i4;
  46.          i+=i5;
  47.          i+=i6;
  48.          i+=i7;
  49.      }
  50.      int i;
  51.      s():i(0){}
  52. };
  53. int main(int argc, char *argv[])
  54. {
  55.         const int l=100000000;
  56.         s* ps=new s[l];
  57.         vector<s*> vps;
  58.         for(int i=0;i<l;++i){
  59.                 ps[i].i=1;
  60.                 vps.push_back(&ps[i]);
  61.         }
  62.         volatile int i=2;
  63.         volatile int j=i+1;


  64.         {
  65.                 DWORD ret1=GetTickCount();
  66.                 std::for_each(vps.begin(),vps.end(),
  67.                         Pred7Var<s,int,int,int,int,int,int,int>(i,j,i,j,i,j,i,&s::f7));
  68.                 DWORD ret2=GetTickCount();
  69.                 printf("%d\n",ret2-ret1);
  70.         }       
  71.         {
  72.                 DWORD ret1=GetTickCount();
  73.                 std::for_each(vps.begin(),vps.end(),[&](s* ps){ps->f7(i,j,i,j,i,j,i);});
  74.                 DWORD ret2=GetTickCount();
  75.                 printf("%d\n",ret2-ret1);
  76.         }
  77.     delete[] ps;
  78.     return EXIT_SUCCESS;
  79. }
复制代码

论坛徽章:
0
3 [报告]
发表于 2012-04-06 12:13 |只看该作者
gcc 4.6.2的测试结果, lambda完胜

第一段
718
452

第二段
1062
718

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
4 [报告]
发表于 2012-04-06 12:15 |只看该作者
我只觉得你的代码很奇怪,尤其是那个 volatile。i 是 volatile,但你传给一个非volatile后,后者不会神奇的自动变为volatile,所以它根本没用
我把代码修了一下
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. #include <ctime>
  5. using namespace std;

  6. template<class C, class T1, class T2>
  7. class Pred2Vars
  8. {
  9. public:
  10.     typedef void (C::*PredPtr)( T1, T2 );

  11.     Pred2Vars( T1 p1, T2 p2, PredPtr pPred ) : m_p1(p1),m_p2(p2),m_pPred(pPred)
  12.     {
  13.     }
  14.     void operator()( C& Object )
  15.     {
  16.         (Object.*m_pPred)( m_p1, m_p2 );
  17.     }
  18. private:
  19.     T1 m_p1;
  20.     T2 m_p2;
  21.     PredPtr m_pPred;
  22. };

  23. struct s
  24. {
  25.     int i;

  26.     explicit s( int val=0 ) : i(val)
  27.     {
  28.     }

  29.     void f2( int a,int b )
  30.     {
  31.         i += a;
  32.         i += b;
  33.     }
  34.     void f7( int i1, int i2, int i3, int i4, int i5, int i6, int i7 )
  35.     {
  36.         i += i1;
  37.         i += i2;
  38.         i += i3;
  39.         i += i4;
  40.         i += i5;
  41.         i += i6;
  42.         i += i7;
  43.     }
  44. };

  45. int main()
  46. {
  47.     const size_t len = 100000000;
  48.     vector<s> vps( len, s(1) );

  49.     const int i = 2;
  50.     const int j = 3;
  51.     {
  52.         clock_t ret1 = clock();
  53.         std::for_each( vps.begin(), vps.end(), Pred2Vars<s,int,int>(i,j,&s::f2) );
  54.         clock_t ret2 = clock();
  55.         cout << ret2-ret1 << endl;
  56.     }
  57.     {
  58.         clock_t ret1 = clock();
  59.         std::for_each( vps.begin(), vps.end(), [i,j](s& object){object.f2(i,j);} );
  60.         clock_t ret2 = clock();
  61.         cout << ret2-ret1 << endl;
  62.     }

  63.     return EXIT_SUCCESS;
  64. }
复制代码

论坛徽章:
0
5 [报告]
发表于 2012-04-06 12:28 |只看该作者
volatile .. 看懂了,楼主就是要探索传值时,lambda有没比functor多了复制次数。

论坛徽章:
0
6 [报告]
发表于 2012-04-06 18:07 |只看该作者
AD8018 发表于 2012-04-06 12:28
volatile .. 看懂了,楼主就是要探索传值时,lambda有没比functor多了复制次数。


是这个意思,但是看反汇编我又看不太懂。
不知道C++11有没有在实现层做规定,这个lambda有没有复制一次变量?

论坛徽章:
1
射手座
日期:2013-08-21 13:11:46
7 [报告]
发表于 2012-04-07 02:28 |只看该作者
lambda和functor应该是一样的效率
都可以被内联

论坛徽章:
0
8 [报告]
发表于 2016-06-18 11:11 |只看该作者
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP