I have some code which looks a bit like this:
std::random_device rd;
#pragma omp parallel
{
std::mt19937 gen(rd());
#pragma omp for
for(int i=0; i < N; i++)
{
/* Do stuff with random numbers from gen() */
}
}
I have a few questions:
- Is
std::random_device
thread safe? i.e. Is it going to do something unhelpful when several threads call it at once? - Is this generally a good idea? Should I be worried about overlapping random number streams?
- Is there a better way to achieve what I want (independent random number streams in each thread - I'm not too worried about reproducibility at the moment)?
In case it make any difference to the workings of std::random_device
I'm primarily running on Windows, though I would like the code to work equally well on Linux and OSX as well.
It's not a good idea to use the random device in parallel. Even if it's blocking you may not have troubles with overlapping random number streams but you add a additional synchronization point.
You should set up as many random number engines (RNE) as many threads you want to start,
omp_get_num_threads()
. Create an std::vector of RNEs and seed them in the sequential part of your program. For seeding you can use the random device and a std::seed_seq.Then use in each thread the RNE associated with with the thread number,
omp_get_thread_num()
.Never use the random device to generate random numbers, its's slow and in general not generating uniformly distributed random numbers!
Depending on the quality of the random numbers you need you can use one of the predefined random number generators. If you are doing Monte Carlo simulations or Cryptography be extra careful what algorithm you choose.
You'll find a lot useful information on random engines at https://en.cppreference.com/w/cpp/numeric/random.