I have the following monte carlo code with openmp multithreading
int main()
{
std::uniform_int_distribution<int> dir(0, 1);
std::uniform_int_distribution<int> xyz(0, 2);
std::uniform_real_distribution<double> angle(0,360);
mt19937 gen{0};
auto M = 20;
long double sum = 0;
auto num_trials = 10000;
// omp_set_num_threads(12);
#pragma omp parallel
{
double loc_sum = 0.0;
#pragma omp for
for(int i = 0; i < num_trials; ++i)
{
double x = 0;
double y = 0;
double z = 0;
double r = 0;
auto N = 0;
while(r < M)
{
auto d = dir(gen);
auto p = xyz(gen);
if(p == 0)
{
x += (d == 1) ? -1 : 1;
}
else if(p == 1)
{
y += (d == 1) ? -1 : 1;
}
else
{
z += (d == 1) ? -1 : 1;
}
r = std::sqrt(x * x + y * y + z * z);
++N;
}
loc_sum += N;
}
#pragma omp critical
sum += loc_sum;
}
}
The variable sum is quite different for executing in serial vs multiple threads. I am expecting a slight difference due to the calls to the random uniform distributions, but the difference that I am observing is too significant and can't be due to randomness, and I suspect there's a bug in my multithreaded code.
Are there any race conditions or data races in this code that's affecting sum?
dirandxyz) without a lock around them. You're also using the PRNG (gen) without locking. Does the code work if you mark the lines to generatedandpwith#pragma omp critical?d,pwith a critical section and it works. I had thought the generators would be produce values atomically. Practically, I don't want to put a critical section aroundd,p. Would the best solution here be to create the generators inside the parallel region?