Problem
I intend to write a C++11 application for Linux which does some numerical simulation (not cryptography) based on approximately one million pseudorandom 32bit numbers. To speed things up, I'd like to perform the simulation in parallel threads using all cores of a desktop CPU. I'd like to use the Mersenne Twister mt19937
provided by boost as the PRNG, and I guess that for performance reasons I should have one such PRNG per thread. Now I'm unsure about how to seed them in order to avoid generating the same subsequence of random numbers in multiple threads.
Alternatives
Here are the alternatives that I have thought of so far:
Seed the PRNG for every thread independently from
/dev/urandom
.I'm a bit worried about the case when the system entropy pool gets exhausted, as I don't know how the system internal PRNG operates. Could it happen that I accidentially get consecutive seeds which exactly identify consecutive states of the Mersenne Twister, due to the fact that
/dev/urandom
is using a Mersenne Twister itself? Probably strongly related to my concerns for the next point.Seed one PRNG from
/dev/urandom
and the others from that first one.Basically the same concern as well: is it good or bad to use one PRNG to seed another that uses the same algorithm? Or in other words, does reading 625 32bit integers from a
mt19937
correspond directly to the internal state of themt19937
generator at any point during this generation?Seed others from first with non-Mersenne information.
As using the same algorithm to generate random numbers and to generate the initial seed feels somehow like it might be a bad idea, I thought about introducing some element which is not dependent on the Mersenne Twister algorithm. For example, I could XOR the thread id into each element of the initial seed vector. Does that make things any better?
Share one PRNG among threads.
This would make sure that there is only one sequence, with all the known and desirable properties of the Mersenne Twister. But the locking overhead required to control access to that generator does worry me somewhat. As I have found no evidence to the contrary, I assume that I as the library user would be responsible for preventing concurrent access to the PRNG.
Pre-generate all random numbers.
This would have one thread generate all the required 1M random numbers up front, to be used by the different threads later on. The memory requirement of 4M would be small compared to that of the overall application. What worries me most in this approach is that the generation of random numbers itself is not concurrent. This whole approach also doesn't scale too well.
Questions
Which of these approaches would you suggest, and why? Or do you have a different suggestion?
Do you know which of my concerns are justified and which are simply due to my lack of insight into how things actually work?
See Question&Answers more detail:os