C++ MC模拟中的openmp专用/共享数据

C++ MC模拟中的openmp专用/共享数据,c++,boost,openmp,montecarlo,C++,Boost,Openmp,Montecarlo,我正在用蒙特卡罗方法模拟一个随机微分方程,这在原则上非常适合openMP,因为不同的实现并不相互依赖。不幸的是,我的代码遇到了一些问题,一旦打开openMP就会产生错误的结果。没有它,它工作得非常好。我的“关键”循环如下所示: double price = 0.0 #pragma omp parallel for private(VOld, VNew) for (long i = 0; i < NSim; ++i){ VOld = S_0; for (long index

我正在用蒙特卡罗方法模拟一个随机微分方程,这在原则上非常适合openMP,因为不同的实现并不相互依赖。不幸的是,我的代码遇到了一些问题,一旦打开openMP就会产生错误的结果。没有它,它工作得非常好。我的“关键”循环如下所示:

double price = 0.0
#pragma omp parallel for private(VOld, VNew)
for (long i = 0; i < NSim; ++i){
    VOld = S_0;
    for (long index = 0; index < Nt; ++index){
        VNew = VOld  + (dt * r * VOld) + (sqrdt * sig * VOld * dW());
        VOld = VNew;
    }
    double tmp = myOption.PayOff(VNew);
    price += (tmp)/double(NSim);
}
双倍价格=0.0
#专用pragma omp并行(VOld,VNew)
对于(长i=0;i

我真的很感激任何帮助。提前感谢:-)

一个常见的错误是忘记每个线程必须有自己的随机数生成器。如果不是这样,那么对dW的每次调用都会弄乱(共享的,而不是私有的)随机数生成器的内部状态


我希望这会有所帮助。

好的,因此基于@jmbr和@raxman的回答,我将内部循环移动到一个单独的函数,并确保
rng
现在是真正私有的。另外,请注意播种技巧,它至关重要。除此之外,我在
选项价格
上引入了
折扣
。下面的代码工作正常

double SimulateStockPrice(const double InitialPrize, const double dt, const long Nt, const double r, const double sig, boost::mt19937 *rng){

    static unsigned long seed = 0;
    boost::mt19937 *rng = new boost::mt19937();
    rng -> seed((++seed) + time(NULL));
    boost::normal_distribution<> nd(0.0, 1.0);
    boost::variate_generator< boost::mt19937, boost::normal_distribution<> > dW(*rng, nd);

    double sqrdt = sqrt(dt);
    double PriceNew(0.0), PriceOld(InitialPrize);

    for (long index = 0; index < Nt; ++index){
        PriceNew = PriceOld  + (dt * r * PriceOld) + (sqrdt * sig * PriceOld * dW());
        PriceOld = PriceNew;
    }

    delete rng;
    return PriceNew;
}
double SimulationStockPrice(常数双初始值、常数双dt、常数长Nt、常数双r、常数双sig、boost::mt19937*rng){
静态无符号长种子=0;
boost::mt19937*rng=新boost::mt19937();
rng->seed(++seed)+时间(NULL));
正态分布nd(0.0,1.0);
boost::variate_generatordW(*rng,nd);
双sqrdt=sqrt(dt);
双倍价格新(0.0),价格旧(初始价格);
对于(长索引=0;索引
然后在我的大循环中:

#pragma omp parallel for default(none) shared(dt, NSim, Nt, S_0, myOption) reduction(+:OptionPrice)
for (long i = 0; i < NSim; ++i){
    double StockPrice = SimulateStockPrice(S_0, dt, Nt, myOption.r, myOption.sig, rng);
    double PayOff     = myOption.myPayOffFunction(StockPrice);
    OptionPrice      += PayOff;
}
#pragma omp parallel用于默认(无)共享(dt、NSim、Nt、S#u 0、myOption)减少(+:OptionPrice)
对于(长i=0;i

接下来:-)

我看到的一个问题是,在变量
price
上有一个竞争条件。你应该减价

#pragma omp parallel for private(VOld, VNew) reduction(+:price)
变量
OptionPrice


在我看来,rng仍然是共享的,而不是私有的。如果您希望它私有或声明它私有,您应该在并行块中定义它(对于私有变量,我更喜欢在并行块中声明它们,这会自动使它们私有,而不是声明它们私有)。

Hi,您能看看我的答案@jmbr吗?正如@raxman在上面指出的,rng仍然是共享的。你播种发电机的方式对我来说仍然很奇怪。我现在不能给你更深入的反馈,但是关于rng,我建议你创建N个独立的实例(其中N是线程数)并仔细地对它们进行种子设定(即,第一个使用gettimeofday进行种子设定,其余的使用刚刚设定的rng生成的随机数进行种子设定),以防止相关性。嗨@jmbr!我更改了代码,现在可以正常工作了。谢谢你的评论。我发现了减少的问题,但这还不够,你说的很好,rng仍然是共享的。我现在编辑了代码,效果很好。谢谢你的评论!:-)