www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - parallel() and random number generation

reply Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
Hello all,

One of the claims made for pseudo-random number generation in D is that rndGen 
(default RNG) is thread-safe, that is, each instance is unique to its thread
and 
is seeded with unpredictableSeed, which should strongly limit the chances of
two 
threads having correlated sequences of pseudo-random numbers.

Now consider the following code:

////////////////////////////////////////////////////////////
import std.random, std.range, std.stdio;

void main()
{
       rndGen.seed(1001);

       foreach(i; iota(12))
             writeln(uniform(0.0, 1.0));
}
////////////////////////////////////////////////////////////

Obviously, because we seed rndGen, this produces exactly the same sequence
every 
time.  But now suppose we use a parallel foreach:

////////////////////////////////////////////////////////////
import std.parallelism, std.random, std.range, std.stdio;

void main()
{
       rndGen.seed(1001);

       foreach(i; iota(12).parallel())
             writeln(uniform(0.0, 1.0));
}
////////////////////////////////////////////////////////////

Now, I'd expect that suddenly a number of the random variates would suddenly 
become unpredictable with each run, and that the number thereof would be 
proportional to the number of threads -- so with 2 threads, we'd expect half
the 
numbers to suddenly be unpredictable with each run -- because only one thread 
would be using the seeded pseudo-random sequence, and the others would be using 
a separate rndGen with unpredictable seed.

But actually, in my experience, the number of random variates that differ from 
the predictable sequence is not in proportion to the number of threads and
often 
corresponds only to the last 3-4 variates.

This is a bit worrying, because it raises the question of whether the same 
rndGen is being used in the different threads, and thus whether in fact threads 
might generate correlated random sequences.

Advice/thoughts/explanations?

Thanks & best wishes,

      -- Joe
Jan 14 2013
parent "Nathan M. Swan" <nathanmswan gmail.com> writes:
On Monday, 14 January 2013 at 22:24:22 UTC, Joseph Rushton 
Wakeling wrote:
 Hello all,

 One of the claims made for pseudo-random number generation in D 
 is that rndGen (default RNG) is thread-safe, that is, each 
 instance is unique to its thread and is seeded with 
 unpredictableSeed, which should strongly limit the chances of 
 two threads having correlated sequences of pseudo-random 
 numbers.

 Now consider the following code:

 ////////////////////////////////////////////////////////////
 import std.random, std.range, std.stdio;

 void main()
 {
       rndGen.seed(1001);

       foreach(i; iota(12))
             writeln(uniform(0.0, 1.0));
 }
 ////////////////////////////////////////////////////////////

 Obviously, because we seed rndGen, this produces exactly the 
 same sequence every time.  But now suppose we use a parallel 
 foreach:

 ////////////////////////////////////////////////////////////
 import std.parallelism, std.random, std.range, std.stdio;

 void main()
 {
       rndGen.seed(1001);

       foreach(i; iota(12).parallel())
             writeln(uniform(0.0, 1.0));
 }
 ////////////////////////////////////////////////////////////

 Now, I'd expect that suddenly a number of the random variates 
 would suddenly become unpredictable with each run, and that the 
 number thereof would be proportional to the number of threads 
 -- so with 2 threads, we'd expect half the numbers to suddenly 
 be unpredictable with each run -- because only one thread would 
 be using the seeded pseudo-random sequence, and the others 
 would be using a separate rndGen with unpredictable seed.

 But actually, in my experience, the number of random variates 
 that differ from the predictable sequence is not in proportion 
 to the number of threads and often corresponds only to the last 
 3-4 variates.

 This is a bit worrying, because it raises the question of 
 whether the same rndGen is being used in the different threads, 
 and thus whether in fact threads might generate correlated 
 random sequences.

 Advice/thoughts/explanations?

 Thanks & best wishes,

      -- Joe
It's thread-safe when you use std.concurrency; std.parallelism is _not_ really safe at all. NMS
Jan 15 2013