3

数学関数を評価するために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++すると、 では速度が 1.5 倍になりますが、 では速度が向上しtemplates functionません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::functionとの 1.5 ゲインを得ることができllvm-g++ますか?

#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());
}
4

1 に答える 1

0

実際に測定せずに、私は思い切って、boost::function(またはstd::functionC ++ 11から)使用することは他の2つのオプションほど効率的ではないと主張します。

その理由は、function型消去を使用して、使用されている実際のファンクターfunctionの型を削除するためです。これは、ポインターによる呼び出しを行う実際のオブジェクトを格納し、関数呼び出しを使用する必要があることを意味します。一方、他の2つの方法では、コンパイラーはロジックをインライン化し、ディスパッチのコストを取り除くことができます。

qsortこれは、実際には、C ++と比較したCライブラリのパフォーマンスの違いによく似ています。ファンクターsortを使用することで、コンパイラーはインライン化と最適化の可能性が高くなります。

別の質問は、これがアプリケーションに影響を与えるかどうかであり、そのために測定する必要があります。IOの全体的なコスト、またはその他の操作がアプリケーションを支配している場合がありますが、これはまったく違いはありません。

于 2012-03-15T13:17:56.293 に答える