Two points - firstly, the example is in Fortran, but I think he should stick to any language; secondly, the built-in random number generators are not really random and other generators exist, but we are not interested in using them for what we do.
Most discussions of random seeds confirm that if the program does not sow it at run time, then the seed is generated at compile time. Thus, the same sequence of numbers is generated each time the program starts, which is not suitable for random numbers. One way to overcome this is to plant a random number generator with a system clock.
However, when working in parallel with MPI on a multi-core machine, the approach to the system clock for us poses the same problems. While the sequences changed from run to run, all processors got the same system clock and thus the same random seed and the same sequences.
So, consider the following code example:
PROGRAM clock_test IMPLICIT NONE INCLUDE "mpif.h" INTEGER :: ierr, rank, clock, i, n, method INTEGER, DIMENSION(:), ALLOCATABLE :: seed REAL(KIND=8) :: random INTEGER, PARAMETER :: OLD_METHOD = 0, & NEW_METHOD = 1 CALL MPI_INIT(ierr) CALL MPI_COMM_RANK(MPI_COMM_WORLD, rank, ierr) CALL RANDOM_SEED(SIZE=n) ALLOCATE(seed(n)) DO method = 0, 1 SELECT CASE (method) CASE (OLD_METHOD) CALL SYSTEM_CLOCK(COUNT=clock) seed = clock + 37 * (/ (i - 1, i = 1, n) /) CALL RANDOM_SEED(put=seed) CALL RANDOM_NUMBER(random) WRITE(*,*) "OLD Rank, dev = ", rank, random CASE (NEW_METHOD) OPEN(89,FILE='/dev/urandom',ACCESS='stream',FORM='UNFORMATTED') READ(89) seed CLOSE(89) CALL RANDOM_SEED(put=seed) CALL RANDOM_NUMBER(random) WRITE(*,*) "NEW Rank, dev = ", rank, random END SELECT CALL MPI_BARRIER(MPI_COMM_WORLD, ierr) END DO CALL MPI_FINALIZE(ierr) END PROGRAM clock_test
That when launched on my workstation with two cores gives:
OLD Rank, dev = 0 0.330676306089146 OLD Rank, dev = 1 0.330676306089146 NEW Rank, dev = 0 0.531503215980609 NEW Rank, dev = 1 0.747413828750221
So, we overcame the clock problem by reading the seed from /dev/urandom
instead. Thus, each core gets its own random number.
What other seed approaches exist that will work in a multi-core MPI system and will still be unique on every kernel, from launch to launch?