2012-04-13 88 views
4

我正在阅读'C++模板完整指南'一书,部分内容是关于元编程。有一个循环展开的例子(17.7)。我已经实现了点积计算程序:C++循环展开效果

#include <iostream> 
#include <sys/time.h> 

using namespace std; 

template<int DIM, typename T> 
struct Functor 
{ 
    static T dot_product(T *a, T *b) 
    { 
     return *a * *b + Functor<DIM - 1, T>::dot_product(a + 1, b + 1); 
    } 
}; 

template<typename T> 
struct Functor<1, T> 
{ 
    static T dot_product(T *a, T *b) 
    { 
     return *a * *b; 
    } 
}; 


template<int DIM, typename T> 
T dot_product(T *a, T *b) 
{ 
    return Functor<DIM, T>::dot_product(a, b); 
} 

double dot_product(int DIM, double *a, double *b) 
{ 
    double res = 0; 
    for (int i = 0; i < DIM; ++i) 
    { 
     res += a[i] * b[i]; 
    } 
    return res; 
} 


int main(int argc, const char * argv[]) 
{ 
    static const int DIM = 100; 

    double a[DIM]; 
    double b[DIM]; 

    for (int i = 0; i < DIM; ++i) 
    { 
     a[i] = i; 
     b[i] = i; 
    } 


    { 
     timeval startTime; 
     gettimeofday(&startTime, 0); 

     for (int i = 0; i < 100000; ++i) 
     { 
      double res = dot_product<DIM>(a, b); 
      //double res = dot_product(DIM, a, b); 
     } 

     timeval endTime; 
     gettimeofday(&endTime, 0); 

     double tS = startTime.tv_sec * 1000000 + startTime.tv_usec; 
     double tE = endTime.tv_sec * 1000000 + endTime.tv_usec; 

     cout << "template time: " << tE - tS << endl; 
    } 

    { 
     timeval startTime; 
     gettimeofday(&startTime, 0); 

     for (int i = 0; i < 100000; ++i) 
     { 
      double res = dot_product(DIM, a, b); 
     } 

     timeval endTime; 
     gettimeofday(&endTime, 0); 

     double tS = startTime.tv_sec * 1000000 + startTime.tv_usec; 
     double tE = endTime.tv_sec * 1000000 + endTime.tv_usec; 

     cout << "loop time: " << tE - tS << endl; 
    } 

    return 0; 
} 

我正在使用xcode,并关闭所有代码优化。根据这本书,我预计模板版本必须更快,然后才能实现简单循环。但结果是(T - 模板,L =环):

DIM 5:T =〜5000,L =〜3500

DIM 50:T =〜55000,L = 16000

DIM 100:t = 130000,l = 36000

此外,我试图使模板函数内联没有性能差异。

为什么简单的循环速度如此之快?

+5

“性能......我把所有的代码优化关闭”(在杰米的声音)有你的问题! – avakar 2012-04-13 14:20:14

+3

您已回答了您自己的问题:“我已关闭所有代码优化”。如果'dot_product'的实例没有内联,那么调用它们将比运行一个循环慢得多。 – 2012-04-13 14:22:11

+3

性能测量的第一条规则 - 使用优化构建。第二条规则 - 不要在调试器中运行。还有更多。 – Skizz 2012-04-13 14:22:49

回答

5

根据编译器的不同,如果不打开性能优化,则可能不会发生循环展开。

这很容易理解为什么:你的递归模板实例基本上是创建一系列函数。编译器无法将所有这些转换为内联的展开循环,并仍然保持可用的明智的调试信息。假设段错误发生在某个函数内部,或者引发异常?你不希望能够获得显示每一帧的堆栈跟踪吗?编译器认为你可能想要这样做,除非你打开优化,这让你的编译器有权访问你的代码。

+0

谢谢,我已经把优化,现在模板更快 – Andrew 2012-04-13 15:08:45