I have several threads running concurrently and each of them must generate random numbers. I want to understand if there is a pattern to follow, to understand if it is correct to initialize the random generator with srand in the main thread or if every thread must initialize its own random generator. It seems that rand/srand have not been designed to be used with threads and I'm wondering how I can deal with threads and random numbers together. Thanks
EDIT: I need pure random numbers, but I'm also interested in generating a deterministic sequence for testing purposes. I'm on linux, but I prefer to write code as portable as possible.
When working with threads and doing e.g simulations or so it is very important that you have the random generators independent. First, dependencies between them can really bias your results and then mechanisms for access control to the state of the random generator will most likely slow down execution.
On POSIX systems (where you seem to be) there is the
*rand48
family of functions whereerand48
,nrand48
andjrand48
take the state of the random generator as input values. So you can easily have independent states in each thread. Those you can initialize with a known number (e.g the number of your thread) and you'd have a reproducible sequence of random numbers. Or you initialize it with something non-predicable such as the current time & the number to have sequences that vary for each execution.On Windows you can use the rand_s() function, which is thread safe. If you are already using Boost, then boost::random is competent (although I appreciate this is tagged C, not C++).
On Linux you can use the rand_r() for a mediocre generator or the drand48_r() function for a much better one. Both are thread safe replacements for
rand()
anddrand48()
, by taking a single argument consisting of the current state, instead of using global state.With regard to your question on initialization, both of the generators above allow you to seed at whatever point you desire, so you are not forced to seed them before spawning your threads.
On Linux systems you can use a function like:
Here I have to say that I don´t really know if numbers generated by this function fit to normal distribution in other words if this function is a valid RNG in the range (min,max) but at least worked for me to write a simple benchmark that required some random numbers.
As you can see, the function utilizes the POSIX thread id in order to re-arrange the random seed. Doing so, each thread has it own random seed instead of using global state depending on
time(NULL)
rand_r is thread-safe but also is reentrant.
Code below generates uint128_t pseuso-random numbers using xorshift algorithm.
Additional properties:
uintx_types.h:
lf.h:
rand.h:
rand.c:
test.c:
Compile with gcc(4.9.2) under Linux.
This link provides some code for reading from /dev/random -- which should be thread-safe -- and the question is along the same lines:
Is reading /dev/urandom thread-safe?