对于下面的代码,它为蒙特卡罗模拟生成随机数,我需要收到每次运行的精确和,但这不会发生,尽管我已经修复了种子。如果有人能指出这段代码的问题,我将不胜感激。
#include <cmath>
#include <random>
#include <iostream>
#include <chrono>
#include <cfloat>
#include <iomanip>
#include <cstdlib>
#include <omp.h>
#include <trng/yarn2.hpp>
#include <trng/mt19937_64.hpp>
#include <trng/uniform01_dist.hpp>
using namespace std;
using namespace chrono;
const double landa = 1;
const double exact_solution = landa / (pow(landa, 2) + 1);
double function(double x) {
return cos(x) / landa;
}
int main() {
int rank;
const int N = 1000000;
double sum = 0.0;
trng::yarn2 r[6];
for (int i = 0; i <6; i++)
{
r[i].seed(0);
}
for (int i = 0; i < 6; i++)
{
r[i].split(6,i);
}
trng::uniform01_dist<double> u;
auto start = high_resolution_clock::now();
#pragma omp parallel num_threads(6)
{
rank=omp_get_thread_num();
#pragma omp for reduction (+: sum)
for (int i = 0; i<N; ++i) {
//double x = distribution(g);
double x= u(r[rank]);
x = (-1.0 / landa) * log(1.0 - x);
sum = sum+function(x);
}
}
double app = sum / static_cast<double> (N);
auto end = high_resolution_clock::now();
auto diff=duration_cast<milliseconds>(end-start);
cout << "Approximation is: " <<setprecision(17) << app << "\t"<<"Time: "<< setprecision(17) << diff.count()<<" Error: "<<(app-exact_solution)<< endl;
return 0;
}发布于 2021-03-23 07:43:08
TL;博士这个问题有两个方面:
我需要收到每一次运行的确切金额,但这种情况不会发生,虽然我已经固定了种子。如果有人能指出这段代码的问题,我将不胜感激。
首先,在rank=omp_get_thread_num();上有一个争用条件,变量rank在所有线程之间共享,以修复可以在并行区域内声明变量rank的问题,因此,使其成为每个线程的私有变量。
#pragma omp parallel num_threads(6)
{
int rank=omp_get_thread_num();
...
}在您的代码中,您不应该期望sum的值对于不同数目的线程是相同的。为什么?
doubles。
(int i= 0;i从每一个计算机科学家应该知道的浮点算法可以读到:
另一个灰色地带涉及括号的解释。由于舍入误差,代数的联想定律不一定适用于浮点数,例如,当x= 1e30,y= -1e30和z=1时,(x+y)+z的表达式(x+y)+z与x+(y+z)的答案完全不同(前者为1,后者为0)。因此,您可以得出浮点加法不是关联的,以及对于不同数量的线程,您可能有不同的sum值的原因。
sum也会得到不同的结果。正如杰罗姆-理查德在评论中指出的那样:
请注意,像Kahan求和这样更精确的算法可以显着地减少舍入问题,同时仍然是相对快速的。
https://stackoverflow.com/questions/66754871
复制相似问题