C ++慢循环计算

时间:2017-07-03 01:37:35

标签: c++ performance loops while-loop montecarlo

对于我正在执行的monte-carlo计算,我有以下循环:

以下变量是预先计算/填充的,定义为:

    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套计算发生(我没有考虑到cdf计算处理通过boost库)。

我是一个低于平均水平的程序员,并且想知道我是否有任何明显的错误,这可能会减慢计算速度。或者是否有任何其他方法来处理可以加快速度的计算。

    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);
   }

1 个答案:

答案 0 :(得分: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。

因此,考虑到你的时间并不是那么糟糕的操作数量。代码有一些改进的空间,但如果你有兴趣加快一些数量级,你可能应该考虑改变你的配方。