zuiwei 发表于 2012-04-06 10:05

为什么C++11的lambda演算速度比用functor还要慢?

本帖最后由 zuiwei 于 2012-04-06 10:06 编辑

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

可是我发现用lambda演算的时候,时间需要的更长。VC2010 sp1编译,代码如下。
这是为什么呢?
#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;
        vector<s*> vps;
        for(int i=0;i<l;++i){
                ps.i=1;
                vps.push_back(&ps);
        }
        volatile int i=2;
        volatile int j=i+1;
    {//2605
                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);
        }
        {//2574
                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;
}

zuiwei 发表于 2012-04-06 11:48

我现在是VC2010编译release版开了/O2,我测试了一下7个参数的情况,发现还是functor比lamdba快:
代码如下: functor运行781ms,lambda运行860ms。我交换了运行的顺序,发现结果不变。
这又是为什么呢?
#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 T3, class T4, class T5, class T6, class T7>class Pred7Var
{
public:
    typedef void (C::*PredPtr)( T1, T2, T3, T4, T5, T6, T7 );

    Pred7Var( T1 p1, T2 p2, T3 p3, T4 p4, T5 p5, T6 p6, T7 p7, PredPtr pPred ) :
    m_p1( p1 ),
      m_p2( p2 ),
      m_p3( p3 ),
      m_p4( p4 ),
      m_p5( p5 ),
      m_p6( p6 ),
      m_p7( p7 ),
      m_pPred( pPred ){}

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

private:
    T1 m_p1;
    T2 m_p2;
    T3 m_p3;
    T4 m_p4;
    T5 m_p5;
    T6 m_p6;
    T7 m_p7;
    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){}
};
int main(int argc, char *argv[])
{
        const int l=100000000;
        s* ps=new s;
        vector<s*> vps;
        for(int i=0;i<l;++i){
                ps.i=1;
                vps.push_back(&ps);
        }
        volatile int i=2;
        volatile int j=i+1;


        {
                DWORD ret1=GetTickCount();
                std::for_each(vps.begin(),vps.end(),
                        Pred7Var<s,int,int,int,int,int,int,int>(i,j,i,j,i,j,i,&s::f7));
                DWORD ret2=GetTickCount();
                printf("%d\n",ret2-ret1);
        }       
        {
                DWORD ret1=GetTickCount();
                std::for_each(vps.begin(),vps.end(),[&](s* ps){ps->f7(i,j,i,j,i,j,i);});
                DWORD ret2=GetTickCount();
                printf("%d\n",ret2-ret1);
        }
    delete[] ps;
    return EXIT_SUCCESS;
}

AD8018 发表于 2012-04-06 12:13

gcc 4.6.2的测试结果, lambda完胜

第一段
718
452

第二段
1062
718

bruceteen 发表于 2012-04-06 12:15

我只觉得你的代码很奇怪,尤其是那个 volatile。i 是 volatile,但你传给一个非volatile后,后者不会神奇的自动变为volatile,所以它根本没用
我把代码修了一下#include <iostream>
#include <vector>
#include <algorithm>
#include <ctime>
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& Object )
    {
      (Object.*m_pPred)( m_p1, m_p2 );
    }
private:
    T1 m_p1;
    T2 m_p2;
    PredPtr m_pPred;
};

struct s
{
    int i;

    explicit s( int val=0 ) : i(val)
    {
    }

    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 main()
{
    const size_t len = 100000000;
    vector<s> vps( len, s(1) );

    const int i = 2;
    const int j = 3;
    {
      clock_t ret1 = clock();
      std::for_each( vps.begin(), vps.end(), Pred2Vars<s,int,int>(i,j,&s::f2) );
      clock_t ret2 = clock();
      cout << ret2-ret1 << endl;
    }
    {
      clock_t ret1 = clock();
      std::for_each( vps.begin(), vps.end(), (s& object){object.f2(i,j);} );
      clock_t ret2 = clock();
      cout << ret2-ret1 << endl;
    }

    return EXIT_SUCCESS;
}

AD8018 发表于 2012-04-06 12:28

volatile .. 看懂了,楼主就是要探索传值时,lambda有没比functor多了复制次数。

zuiwei 发表于 2012-04-06 18:07

AD8018 发表于 2012-04-06 12:28 static/image/common/back.gif
volatile .. 看懂了,楼主就是要探索传值时,lambda有没比functor多了复制次数。

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

egmkang 发表于 2012-04-07 02:28

lambda和functor应该是一样的效率
都可以被内联

sytpb 发表于 2016-06-18 11:11

http://blog.csdn.net/cywosp/article/details/9379403
页: [1]
查看完整版本: 为什么C++11的lambda演算速度比用functor还要慢?