【问题标题】:llvm g++ and boost functionllvm g++ 和 boost 函数
【发布时间】:2012-03-15 12:49:41
【问题描述】:

我正在尝试确定 boost::function 引入的用于评估数学函数的时间开销与使用 function templates 相比是否可以忽略不计。

我使用的基准测试代码如下。

对于传统的g++boost::function 的开销可以忽略不计:

$ g++ -O3 main.cxx 
$ ./a.out
METHOD              INTEGRAL  TIME TO COMPUTE (SEC)         
Direct              0.379885  3.360000                      
Function template   0.379885  3.380000                      
Boost function      0.379885  3.400000   

对于llvm-g++templates function 的速度增益为 1.5 倍,但 boost::function 没有增益。

$ llvm-g++ -O3 main.cxx
METHOD              INTEGRAL  TIME TO COMPUTE (SEC)         
Direct              0.379885  2.170000                      
Function template   0.379885  2.160000                      
Boost function      0.379885  3.360000    

boost::functionllvm-g++ 是否可以获得 1.5 的增益?

#include <boost/function.hpp>
#include <math.h>
#include <stdio.h>

typedef unsigned int UInt;

using namespace std;

//=============================================================================
// chrono
//=============================================================================
class Chrono
{
    clock_t t1_,t2_,dt_;
    public:
        Chrono(){}
        void   start() { t1_=clock(); };
        void   stop()  { t2_=clock(); };
        double diff()  { return ( (double)( t2_ - t1_) ) / CLOCKS_PER_SEC; };
};

//=============================================================================
// function to integrate
//=============================================================================
inline double fct(double x)
{
    return 1. / (1.+exp(x));
}

//=============================================================================
// using direct method
//=============================================================================
double direct(double a, double b, UInt numSamplePoints)
{
    double delta = (b-a) / (numSamplePoints-1);
    double sum = 0.;
    for (UInt i=0; i < numSamplePoints-1; ++i)
        sum += 1. / (1. + exp(a + i*delta));
    return sum * delta;
}

//=============================================================================
// using function template
//=============================================================================
template<double functionToIntegrate(double)>
double integrate(double a, double b, UInt numSamplePoints)
{
    double delta = (b-a) / (numSamplePoints-1);
    double sum = 0.;
    for (UInt i=0; i < numSamplePoints-1; ++i)
        sum += functionToIntegrate(a + i*delta);
    return sum * delta;
}

//=============================================================================
// using Boost function
//=============================================================================
typedef boost::function<double ( double )> fct_type;

class IntegratorBoost {
    public:
    fct_type functionToIntegrate;
    IntegratorBoost(fct_type fct): functionToIntegrate(fct){}
    double integrate(double a, double b, UInt numSamplePoints)
    {
        double delta = (b-a) / (numSamplePoints-1);
        double sum = 0.;
        for (UInt i=0; i < numSamplePoints-1; ++i)
        sum += functionToIntegrate(a + i*delta);
        return sum * (b-a) / numSamplePoints;
    }
};

//=============================================================================
// main
//=============================================================================
int main()
{
    double integral;
    UInt numSamplePoints = 5E07;
    Chrono chrono;

    printf("%-20s%-10s%-30s\n","METHOD","INTEGRAL","TIME TO COMPUTE (SEC)");

    // Direct
    chrono.start();
    integral = direct(0., 1., numSamplePoints);
    chrono.stop();
    printf("%-20s%-10f%-30f\n","Direct",integral,chrono.diff());

    // Function template
    chrono.start();
    integral = integrate<fct>(0., 1.,numSamplePoints);
    chrono.stop();
    printf("%-20s%-10f%-30f\n","Function template",integral,chrono.diff());

    // Boost function
    chrono.start();
    IntegratorBoost intboost(fct);
    integral = intboost.integrate(0.,1.,numSamplePoints);
    chrono.stop();
    printf("%-20s%-10f%-30f\n","Boost function",integral,chrono.diff());
}

【问题讨论】:

  • 使用clock 进行基准测试并不是那么可靠。我怀疑它可能会严重扭曲您的结果,使它们变得毫无意义。
  • 在 Linux 上,我会推荐 gettimeofday 以获得更精确的计时器。此外,llvm-g++ 已被弃用(并且基于 g++ 4.2),我建议切换到 Clang 3.0 以获得更好的一致性和新的闪亮的 C++11。
  • 我还会计时一个 lambda 函数,看看它是如何叠加的。它具有boost::function 的所有优势和较低级别的编译器支持。
  • @MatthieuM。精确定时器的正确函数是clock_gettime(CLOCK_MONOTONIC,...)

标签: c++ g++ llvm boost-function


【解决方案1】:

如果没有实际测量,我将冒险并声称使用 boost::function(或来自 C++11 的 std::function)不能像其他两个选项一样有效。

原因是 function 使用类型擦除来删除正在使用的实际 functor 的类型,这意味着 function 需要存储通过以下方式进行调用的实际对象指针和使用函数调用。另一方面,在其他两种方法中,编译器能够内联逻辑并消除调度成本。

这实际上与多次提到的 C 库 qsort 与 C++ sort 的性能差异非常相似,其中通过使用 仿函数,编译器有更好的内联和优化机会.

那么另一个问题是,这是否会对您的应用程序产生影响,并且您需要对此进行衡量。可能是 IO 的总体成本或任何其他操作在您的应用程序中占主导地位,这根本不会产生影响。

【讨论】:

    猜你喜欢
    • 2014-03-11
    • 1970-01-01
    • 2013-05-19
    • 2011-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-14
    • 1970-01-01
    相关资源
    最近更新 更多