Thread-safe uniform random number generator
Asked Answered
M

8

6

I have some parallel Fortran90 code in which each thread needs to generate the same sequence of random numbers.

I have a random number generator that seems to be thread-unsafe, since, for a given seed, I'm completely unable to repeat the same results each time I run the program.

I surfed unsuccessfully (almost) the entire web looking for some code of a thread-safe RNG. Could anyone provide me with (the link to) the code of one?

Thanks in advance!

Mcilwain answered 2/3, 2009 at 13:14 Comment(3)
How is the application parallelized? You might handle this differently if you are using something like MPI.Dimidiate
By now it is parallelized using OpenMP but in a near future, I will parallelize it using MPIMcilwain
I also maintain one bitbucket.org/LadaF/elmm/src/… an improved version of cmiss.org/openCMISS/wiki/RandomNumberGenerationWithOpenMPJacksmelt
A
6

A good Pseudorandom number generator for Fortran90 can be found in the Intel Math Kernel Vector Statistical Library. They are thread safe. Also, why does it need to be threadsafe? If you want each thread to get the same list, instantiate a new PRNG for each thread with the same seed.

Andromada answered 2/3, 2009 at 13:59 Comment(0)
R
3

Most repeatable random number generators need state in some form. Without state, they can't do what comes next. In order to be thread safe, you need a way to hold onto the state yourself (ie, it can't be global).

Rescue answered 2/3, 2009 at 13:37 Comment(0)
E
2

When you say "needs to generate the same sequence of random numbers" do you mean that

  • Each thread needs to generate a stream of numbers identical to the other thread? This implies choosing the seed before peeling off threads, then instantiating the a thread-local PRNG in each thread with the same seed.

or

  • You want to be able to repeat the same sequence of numbers between different runs of the programs, but each thread generates it's own independent sequence? In this case, you still can't share a single PRNG because the thread operation sequence is non-deterministic. So seed a single PRNG with a known seed before launching threads, and use it to generate the initial seeds for the threads. Then you instantiate thread-local generators in each thread...

In each of these cases you should note what Neil Butterworth say about the statistics: most of the usual guarantees that the PRNG like to claim are not reliable when mix streams generated in this way.


In both cases you need a thread-local PRNG. I don't know what is available in f90...but you can also write you own (lookup Mersenne Twister, and write a routne that takes the saved state as a parameter...).

In fortran 77, this would look something like

      function PRNGthread (state)

      double state(statesize)

c stuff happens here which uses and manipulates the state vector...

      PRNGthread = result
      return 

and each of your threads should maintain a separate state vector, though all will use the same initial value.

Esoterica answered 2/3, 2009 at 16:11 Comment(0)
N
1

I understand you need every thread to produce the same stream of random numbers.

A very good Pseudo Random Generator that will generate a reproducable stream of numbers and is quite fast is the MT19937. Just make sure that you generate the seed before spawning off the threads, but generate a separate instance of the MT in every thread (make the instance of the MT thread local). That way it will be guaranteed that every MT will produce the same stream of numbers.

Neuropathy answered 2/3, 2009 at 16:23 Comment(0)
T
1

How about SPRNG? I have not tried it myself though.

Twandatwang answered 2/3, 2009 at 17:20 Comment(0)
P
1

I coded a thread-safe Fortran 90 version of the Mersenne Twister/MT19973. The state of the PRNG is saved in a derived type (randomNumberSequence), and you use procedures to seed the generator or get the next element in the sequence.

See http://code.google.com/p/i3rc-monte-carlo-model/source/browse/trunk/Code/RandomNumbersForMC.f95

Pristine answered 6/3, 2010 at 4:8 Comment(0)
B
0

This article https://www.cmiss.org/openCMISS/wiki/RandomNumberGenerationWithOpenMP does not only link to a Fortran implementation, but mentions key points needed to make a PRNG usable with threads. The most important point is:

The Fortran90 version of Ziggurat has several variables and arrays with the 'SAVE' attribute. In order to parallelize the uniform RNG, then, it appears that the required changes are to make these variables arrays with a separate value for each thread (beware of false sharing). Then when the PRNG function is called, we must pass the thread number, and use the corresponding state value.

Bernettabernette answered 2/3, 2009 at 13:14 Comment(0)
P
0

The alternatives seem to be:

  • Use a synchronisation object (such as a mutex) on the generator's seed value. This will unfortunately serialise your code on accesses to generator
  • Use thread-local storage in the generator so each thread gets its own seed - this may cause statstical problems for your app
  • If your platform supports a suitable atomic operation, use that on the seed (it probably won't, however)

Not a very encouraging list, I know. And to add to it, I have no idea how to implement any of them in FORTRAN!

Protecting answered 2/3, 2009 at 13:43 Comment(2)
Bah. Fortran 90 isn't any less capable than C.Kreager
I know - FORTRAN IV was my first language. I meant that "I personally" don't know how to implement them in modern fortran.Protecting

© 2022 - 2024 — McMap. All rights reserved.