How to make each thread use its own RNG in C ++ 11

I use random number generators in C ++ 11. Although there are different opinions, from this thread it seems that most believe that they are not thread safe. As a result, I would like to create a program in which each thread uses its own RNG.

The following example provides an example of how to do this using OpenMP:

#include <random> #include <iostream> #include <time.h> #include "omp.h" using namespace std; int main() { unsigned long long app = 0; { //mt19937_64 engine((omp_get_thread_num() + 1)); //USE FOR MULTITHREADING mt19937_64 engine; //USE FOR SINGLE THREAD uniform_real_distribution<double> zeroToOne(0.0, 1.0); //#pragma omp parallel for reduction(+:app) //USE FOR MULTITHREADING for (unsigned long long i = 0; i < 2000000000; i++) { if(zeroToOne(engine) < 0.5) app++; } } cout << app << endl; return 0; } 

When I run the multi-threaded and single-threaded version of this program and track the time, they take the same amount of time to finish after execution. In addition, the app does not have the same size in two cases, but I suspect that it is simply due to different seeds.

Question Does the above example correctly show how to force each thread to use its own RNG? If not, can I see an example of how this is done, or get a link to some place where they explain how to do this?

+7
source share
2 answers

You should not share instances of a random engine between multiple threads. You must either block one engine, or create one engine for each thread (with a different seed (note the e4e5f4 answer on creating parallel MT engines)). In the case of OpenMP, you can easily save one engine per thread in the vector and get it from the result omp_get_thread_num() , which is between 0 and omp_get_num_threads()–1 .

 class RNG { public: typedef std::mt19937 Engine; typedef std::uniform_real_distribution<double> Distribution; RNG() : engines(), distribution(0.0, 1.0) { int threads = std::max(1, omp_get_max_threads()); for(int seed = 0; seed < threads; ++seed) { engines.push_back(Engine(seed)); } } double operator()() { int id = omp_get_thread_num(); return distribution(engines[id]); } std::vector<Engine> engines; Distribution distribution; }; int main() { RNG rand; unsigned long app = 0; #pragma omp parallel for reduction(+:app) for (unsigned long long i = 0; i < 2000000000; i++) { if(rand() < 0.5) app++; } } 
+6
source

I would refrain from accidentally sowing. This can lead to thread blocking. This will ultimately affect the final statistics.

I would suggest some proven solutions like this

+2
source

All Articles