I have a bunch of threads, each one needs a thread safe random number. Since in my real program threads are spawned and joined repeatedly, I wouldn't like to create random_device and mt19937 each time I enter a new parallel region which calls the same function, so I put them as static:
#include <iostream> #include <random> #include <omp.h> void test(void) { static std::random_device rd; static std::mt19937 rng(rd()); static std::uniform_int_distribution<int> uni(1, 1000); int x = uni(rng); # pragma omp critical std::cout << "thread " << omp_get_thread_num() << " | x = " << x << std::endl; } int main() { # pragma omp parallel num_threads(4) test(); } I cannot place them as threadprivate because of Error C3057: dynamic initialization of 'threadprivate' symbols is not currently supported. Some sources say random_device and mt19937 are thread safe, but I haven't managed to find any docs which would prove it.
- Is this randomization thread safe?
- If no, which of the static objects can be left as static to preserve thread safety?
uni(rng)and interfere with random number generation.rd,rnganduniare objects and their states are shared across multiple threads without synchronization.static thread_localif that helps, not sure about openmp compatibility. Ifrdis used only for initialization, considerrng(std::random_device{}()));mt19937andunihave state inside them that they modify to create the random numbers. Because they modify themselves, they need to be protected if you are sharing them between threads.staticvariables are guaranteed to be accessed in a thread-safe manner, otherwise Meyers singletons would not work. It is theuni(rng)that is the issue.