2017-07-03 7 views
2

私は行っておりモンテカルロ計算のために次のループを有する:C++低速ループ計算

を以下の変数がポピュレート/事前計算され、次のように定義される。whileループ

w_ = std::vector<std::vector<double>>(150000, std::vector<double>(800)); 
    C_ = Eigen::MatrixXd(800,800); 
    Eigen::VectorXd a(800); 
    Eigen::VectorXd b(800); 

を私はnPaths * m = 150,000 * 800 = 120,000,000回の計算が起こっていることを理解しています(私は、ブーストライブラリによって処理されるcdf計算を考慮していません)。

私は平均的なプログラマーよりも低く、私が作っている明白な間違いがあれば計算が遅くなるかもしれないと思っていました。あるいは、計算を処理するための他の方法があります。

int N(0); 
    int nPaths(150000); 
    int m(800); 
    double Varsum(0.); 
    double err; 
    double delta; 
    double v1, v2, v3, v4; 

    Eigen::VectorXd d = Eigen::VectorXd::Zero(m); 
    Eigen::VectorXd e = Eigen::VectorXd::Zero(m); 
    Eigen::VectorXd f = Eigen::VectorXd::Zero(m); 
    Eigen::VectorXd y; 
    y0 = Eigen::VectorXd::Zero(m); 
    boost::math::normal G(0, 1.); 
    d(0) = boost::math::cdf(G, a(0)/C_(0, 0)); 
    e(0) = boost::math::cdf(G, b(0)/C_(0, 0)); 
    f(0) = e(0) - d(0); 
    while (N < (nPaths-1)) 
    { 
     y = y0; 
     for (int i = 1; i < m; i++) 
     { 
      v1 = d(i - 1) + w_[N][(i - 1)]*(e(i - 1) - d(i - 1)); 
      y(i - 1) = boost::math::quantile(G, v1); 
      v2 = (a(i) - C_.row(i).dot(y))/C_(i, i); 
      v3 = (b(i) - C_.row(i).dot(y))/C_(i, i); 
      d(i) = boost::math::cdf(G, v2); 
      e(i) = boost::math::cdf(G, v3); 
      f(i) = (e(i) - d(i))*f(i - 1); 
     } 

     N++; 
     delta = (f(m-1) - Intsum)/N; 
     Intsum += delta; 
     Varsum = (N - 2)*Varsum/N + delta*delta; 
     err = alpha_*std::sqrt(Varsum); 
    } 
+0

時間を費やしている場所を確認するためにコードをプロファイルします。 Linuxを使用している場合は、次を参照してください。https://stackoverflow.com/questions/375913 –

+1

完全最適化でコンパイルしましたか? Linuxでは、コンパイラのコマンドラインに '-O2'または' -O3'を渡します。 – selbie

+0

あなたのコードに徹底的なコメントを書いていないということは問題です。あなたが意図したことの良い説明がないと、コードを改善する方法を言うのは難しいです。それはあなたの質問のコードをコンパイルすることが可能だった場合にも非常に役立つだろう:それは推測では、それを把握する必要があります。役立つ回答を得るには、できるだけ役立つ質問を提供してください。 – Richard

答えて

1

私はあなたのコードの権利を理解していれば、実行している時間は、実際にO(m)操作を必要と内積C_.row(i).dot(y)によるO(nPaths*m*m)=10^11です。

あなたはそれを2回計算しないことにより、2つの要因によって、プログラムを高速化できます。

double prod=C_.row(i).dot(y) 
v2 = (a(i) - prod)/C_(i, i); 
v3 = (b(i) - prod)/C_(i, i); 
を多分コンパイラはすでにあなたのためにそれを行います。

もう1つは、yがゼロから構成されていることです(少なくとも最初は)ので、現在の値がiになるまで、完全なドットプロダクトを実行する必要はありません。それは別の要因2のスピードアップをもたらすはずです。

あなたのタイミングは非常に悪くない操作の完全な数をアカウントに取り込まれます。コードの改善の余地がありますが、いくつかの命令を高速化することに興味がある場合は、おそらく処方の変更について考えるべきです。