2016-03-20 33 views
0

我目前正在尝试执行任意作业的大循环的各种实现的基准,并且当我使用boost转换迭代器和boost counting_iterators时,发现自己的版本非常慢。性能问题与boost transform_iterator和counting_iterator

我设计了一个小代码,用于测试两个循环,它们用0和SIZE-1之间的所有整数的乘积与任意整数(我为了避免溢出而选择1)进行比较。

她是我的代码:

//STL 
#include <iostream> 
#include <algorithm> 
#include <functional> 
#include <chrono> 

//Boost 
#include <boost/iterator/transform_iterator.hpp> 
#include <boost/iterator/counting_iterator.hpp> 

//Compile using 
// g++ ./main.cpp -o test -std=c++11 

//Launch using 
// ./test 1 

#define NRUN 10 
#define SIZE 128*1024*1024 

struct MultiplyByN 
{ 
    MultiplyByN(size_t N): m_N(N){}; 
    size_t operator()(int i) const { return i*m_N; } 
    const size_t m_N; 
}; 

int main(int argc, char* argv[]) 
{ 
    int N = std::stoi(argv[1]); 
    size_t sum = 0; 
    //Initialize chrono helpers 
    auto start = std::chrono::steady_clock::now(); 
    auto stop = std::chrono::steady_clock::now(); 
    auto diff = stop - start; 
    double msec=std::numeric_limits<double>::max(); //Set min runtime to ridiculously high value 
    MultiplyByN op(N); 


    //Perform multiple run in order to get minimal runtime 
    for(int k = 0; k< NRUN; k++) 
    { 
     sum = 0; 
     start = std::chrono::steady_clock::now(); 
     for(int i=0;i<SIZE;i++) 
     { 
      sum += op(i); 
     } 
     stop = std::chrono::steady_clock::now(); 
     diff = stop - start; 
     //Compute minimum runtime 
     msec = std::min(msec, std::chrono::duration<double, std::milli>(diff).count()); 
    } 
    std::cout << "First version : Sum of values is "<< sum << std::endl; 
    std::cout << "First version : Minimal Runtime was "<< msec << " msec "<< std::endl; 
    msec=std::numeric_limits<double>::max(); //Reset min runtime to ridiculously high value 

    //Perform multiple run in order to get minimal runtime 
    for(int k = 0; k< NRUN; k++) 
    { 
     start = std::chrono::steady_clock::now(); 

     //Functional way to express the summation 
     sum = std::accumulate( boost::make_transform_iterator(boost::make_counting_iterator(0), op), 
         boost::make_transform_iterator(boost::make_counting_iterator(SIZE), op), 
         (size_t)0, std::plus<size_t>()); 

     stop = std::chrono::steady_clock::now(); 
     diff = stop - start; 
     //Compute minimum runtime 
     msec = std::min(msec, std::chrono::duration<double, std::milli>(diff).count()); 
    } 
    std::cout << "Second version : Sum of values is "<< sum << std::endl; 
    std::cout << "Second version version : Minimal Runtime was "<< msec << " msec "<< std::endl; 
    return EXIT_SUCCESS; 
} 

和输出我得到:

./test 1 
First version : Sum of values is 9007199187632128 
First version : Minimal Runtime was 433.142 msec 
Second version : Sum of values is 9007199187632128 
Second version version : Minimal Runtime was 10910.7 msec 

我的循环使用的std ::积累“功能性”的版本比简单的循环慢25倍版本,为什么如此?

预先感谢您的帮助

+0

您是否编译启用了编译器优化? (gcc和clang为-O2,Release为MSCV)否则,结果是没有意义的。 –

+2

我用gcc(C++ 14)尝试了boost 1.60和“-o2” - 第二个版本每次运行它都会更快一点....(121ms和118ms)... – PiotrNycz

回答

1

基于代码的评论,你与

g++ ./main.cpp -o test -std=c++11 

编译这个既然你没有指定优化级别,G ++使用默认设置,即-O0即没有优化。

这意味着编译器没有内联任何东西。像标准库或boost这样的模板库依赖内联来提高性能。另外,编译器会产生很多额外的代码,这远不是最优的 - 在这样的二进制文件上进行性能比较没有任何意义。

重新编译启用优化,并再次尝试您的测试以获得有意义的结果。

+0

性能确实很高使用-O3标志更好,对于使用此标志的两种方法,我都获得了大约100ms的时间。谢谢 – Tobbey