2017-07-03 35 views
2

我有以下循環用於蒙特卡洛計算我執行:下面C++慢環計算

變量是預先計算/填充並且被定義爲:

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

while循環我花了570秒左右的時間進行計算。剛開始我知道我有nPaths * m = 150,000 * 800 = 120,000,000個計算集(我沒有考慮到由boost庫處理的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(nPaths*m*m)=10^11,由於點積C_.row(i).dot(y)這就需要O(m)操作。

您可以通過以下兩種因素的不計算兩次加速程序:

double prod=C_.row(i).dot(y) 
v2 = (a(i) - prod)/C_(i, i); 
v3 = (b(i) - prod)/C_(i, i); 

但也許已經編譯器會爲你。

另一件事是,y由零組成(至少在開頭),所以你不必做完整的點積,但只有當前值爲i。這應該給另一個因素2加速。

因此,考慮到操作的絕對數量,您的時間安排並不那麼糟糕。代碼有一些改進的餘地,但如果你有興趣加快一些數量級,你可能應該考慮改變你的公式。