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:
std::random_device
thread safe? i.e. Is it going to do something unhelpful when several threads call it at once?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.
There's no docs on the thread safety of this, but it appears to have no state. Hence it should be thread-safe.
An object is thread-safe for reading from multiple threads. For example, given an object A, it is safe to read A from thread 1 and from thread 2 simultaneously. If an object is being written to by one thread, then all reads and writes to that object on the same or other threads must be protected.
No, they're not thread-safe.
It isn't thread safe, insert from two threads and you can end up in an inconstant state.
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.
On Windows without WinRT, it uses CryptGenRandom
, which is thread-safe by https://stackoverflow.com/a/46171432/2024042
On Windows with WinRT, it uses CryptographicBuffer::GenerateRandom
. There's no docs on the thread safety of this, but it appears to have no state. Hence it should be thread-safe.
On Linux, it seems to read from /dev/urandom
, which is thread-safe.
I read this implementation from libs/random/src/random_device.cpp
.
I have no idea what _CXXRT_STD_NAME
is in that file, and googling this produces boost::random_device as the only result. Maybe it's nothing!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With