Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using stdlib's rand() from multiple threads

I have several threads which all run the same function. In each of these they generate a different random number several times. We tried to do this by putting srand(time(0)) at the start of the function, but it seems that they all get the same number.

Do we need to call srand(time(0)) only once per program, i.e at the start of main (for example), at the start of each function that is called several times, or something else?

like image 767
SIMEL Avatar asked May 28 '11 11:05

SIMEL


People also ask

Is rand () thread-safe?

The function rand() is not reentrant or thread-safe, since it uses hidden state that is modified on each call.

Can multiple threads run the same function?

There is nothing wrong in calling same function from different threads. If you want to ensure that your variables are consistent it is advisable to provide thread synchronization mechanisms to prevent crashes, racearound conditions.

Why is rand () giving me the same number?

The RAND function in stand-alone applications generates the same numbers each time you run your application because the uniform random number generator that RAND uses is initialized to same state when the application is loaded.

Does rand () include 1?

@jonas: the rand documentation states "returns a single uniformly distributed random number in the interval (0,1)", so it clearly excludes zero and one.


3 Answers

srand() seeds the random number generator. You should only have to call srand(time(NULL)) once during startup.

That said, the documentation states:

The function rand() is not reentrant or thread-safe, since it uses hidden state that is modified on each call. This might just be the seed value to be used by the next call, or it might be something more elaborate. In order to get reproducible behaviour in a threaded application, this state must be made explicit. The function rand_r() is supplied with a pointer to an unsigned int, to be used as state. This is a very small amount of state, so this function will be a weak pseudo-random generator. Try drand48_r(3) instead.

The emphasized part of the above is probably the reason why all your threads get the same number.

like image 134
Frédéric Hamidi Avatar answered Oct 11 '22 03:10

Frédéric Hamidi


As you are using C++, rather than C, you may be able to avoid the threading problems often associated with srand/rand by using c++11. This depends on using a recent compiler which supports these features. You would use a separate engine and distribution on each thread. The example acts like a dice.

#include <random>
#include <functional>

std::uniform_int_distribution<int> dice_distribution(1, 6);
std::mt19937 random_number_engine; // pseudorandom number generator
auto dice_roller = std::bind(dice_distribution, random_number_engine);
int random_roll = dice_roller();  // Generate one of the integers 1,2,3,4,5,6.

I referred to Wikipedia C++11 and Boost random when answering this question.

like image 10
kshepherd Avatar answered Oct 11 '22 03:10

kshepherd


From the rand man page:

The function rand() is not reentrant or thread-safe, since it uses hidden state that is modified on each call.

So don't use it with threaded code. Use rand_r (or drand48_r if you're on linux/glibc). Seed each RNG with a different value (you could seed a first RNG in the main thread to produce random seeds for the ones in each thread).

like image 8
Mat Avatar answered Oct 11 '22 04:10

Mat