Search code examples
c++randomopenmpmontecarlo

Private setction and classes OMP, Random C++. Problem with understanding with a result


The task is to calculate PI with MonteCarlo and OpenMP. The code is below:

#include <omp.h>
#include <chrono>
#include <iostream>
#include <random>

#define numSamples 10000000

int main() {

    double I, t1, t2, x, y;
    std::default_random_engine engine;
    auto seed = std::chrono::system_clock::now().time_since_epoch().count();
    std::uniform_real_distribution<double> distr(-1.0, 1.0);
    engine.seed(seed);


    size_t counter = 0;

    t1 = omp_get_wtime();

#pragma omp parallel for reduction(+ : counter) private(x, y) firstprivate(engine, distr)
    for (size_t i = 0; i < numSamples; ++i) {

        x = distr(engine);
        y = distr(engine);

        if (x * x + y * y <= 1) {
            counter++;
        }
    }

    t2 = omp_get_wtime();

    I = 4.0 * (double)counter / numSamples;
    std::cout << "I = " << I << ", t = " << t2 - t1 << "." << std::endl;

    return 0;
}

There is a question. I should have the engine variable private for every thread and it's understandable. But as I've noticed there is no need for making distr variable private. There is no race conditions in this case (the execution time of the program is the same if this variable private or not). Why it happens this way?


Solution

  • std::uniform_real_distribution<double> is a simple helper class. It stores two variables that indicate the range of the distribution and that's it. Its operator () is a const method. So using it in several threads shouldn't cause any data races.

    That's being said, I don't remember it being promised by the standart - not that I read it much - and copying it takes little to no time and space. So why not copy just in case? not that anybody should really care about it. Probably writer didn't bother. Though, there could be various implementations of C++11 with odd stuff.

    However, in CUDA C++ and GPU environment being privately owned by a thread typically results in a better performance over shared ownership (but not always). Though I don't know whether "omp.h" can utilize something like that or not.