蒙特卡罗模拟向量的优化积累

时间:2016-12-05 16:29:18

标签: c++ performance optimization montecarlo

我想优化以下代码:

在蒙特卡罗模拟过程中,我累积了一些f(x)f(x)计算成本很高)并在每个采样步骤后将它们保存在数组bins中。

编辑:f(x)不是x的确定性函数(我的意思是它生成伪随机数并使用它们来修改结果)并且还取决于先前的计算值f(y)

for(int n=0;n<N;n++)
{
    // compute some values f(x) at points "p"
    for(auto k: p) bins[k] += f(k);
}

p.size()远小于bins的大小,但最终会设置大多数元素。

在模拟之后,我通过对bins进行加权求和来累积我的最终值(g是另一个数组中的查找):

for(int l=0;l<M;l++)
    for(int k=0;k<bins.size();k++)
        finalResult[l] += g(k,l)*bins[k];

我当然可以在每个采样步骤后计算更新后的finalResult,但由于循环超过M,这会使程序减慢很多。

我已经尝试了一个非常基本的boost::accumulate,但这并没有提高性能(如果我坚持使用这种设计,我将不得不最终使用它,因为稳定性)。

所有数组都是Eigen::MatrixXd类型,因为我需要它们进行BLAS操作。

p.size() < 10^2
N ~ 10^7
M ~ 10^4
bins.size() ~ 10^5

您对此处的优化技术有何建议?

2 个答案:

答案 0 :(得分:1)

尝试为每个f(x)值(即memoization)计算N一次。例如,如果N很大(就像在这种情况下那样),请尝试将循环更改为以下内容:

static std::unordered_map<unsigned int, double> memoizedFunction;
for(int n=0;n<N;n++)
{
    // compute some values f(x) at points "p"
    for(auto k: p) 
    {
        auto it = memoizedFunction.find( k );
        if (it == memoizedFunction.end())
        {
             it = memoizedFunction.emplace( f(k) ).first;
        }

        bins[k] += *it;
    }
}

或者,您可以在k中存储hit广告符箱bins[k]的次数,然后在最后通过并计算bins[k] * f(k) k

答案 1 :(得分:0)

  

这里只是一个想法,但你可以验证f(x)是线性的   转换然后你可以创建矩阵 A ,使

[f(x)] = A[x] where [x] is the coordinates of x with respect to some basis B.
     

这可以使f(x)更容易和更快地计算,特别是如果x   存在于基数较小的向量空间中。

     

然而,如果在坐标和答案之间进行转换是昂贵的   这可以全面消除任何好处(只记住这一点)。

     

以下是一些可以帮助解释矩阵表示的链接   线性变换。

     

https://math.colorado.edu/~nita/MatrixRepresentations.pdf   https://math.dartmouth.edu/archive/m24w07/public_html/Lecture12.pdf   https://en.wikipedia.org/wiki/Transformation_matrix