2017-07-03 81 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加速。

因此,考虑到操作的绝对数量,您的时间安排并不那么糟糕。代码有一些改进的余地,但如果你有兴趣加快一些数量级,你可能应该考虑改变你的公式。