Due punti: in primo luogo, l'esempio è in Fortran, ma penso che dovrebbe valere per qualsiasi lingua; in secondo luogo, i generatori di numeri casuali incorporati non sono realmente casuali e altri generatori esistono, ma non siamo interessati a usarli per quello che stiamo facendo.Possibili origini per numero casuale semi
La maggior parte delle discussioni su semi casuali riconosce che se il programma non lo semina in fase di esecuzione, il seed viene generato in fase di compilazione. Quindi, la stessa sequenza di numeri viene generata ogni volta che viene eseguito il programma, il che non va bene per i numeri casuali. Un modo per superare questo è quello di seminare il generatore di numeri casuali con l'orologio di sistema.
Tuttavia, quando si esegue in parallelo con MPI su una macchina multi-core, l'approccio dell'orologio di sistema per noi ha generato lo stesso tipo di problemi. Mentre le sequenze sono cambiate da esecuzione a esecuzione, tutti i processori hanno ottenuto lo stesso clock di sistema e quindi la stessa sequenza casuale e le stesse sequenze.
Quindi considerare il seguente codice di esempio:
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
automatica da eseguire sulla mia workstation con 2 core, dà:
OLD Rank, dev = 0 0.330676306089146
OLD Rank, dev = 1 0.330676306089146
NEW Rank, dev = 0 0.531503215980609
NEW Rank, dev = 1 0.747413828750221
Così, abbiamo superato il problema orologio leggendo il seme da /dev/urandom
anziché. In questo modo ogni core riceve il proprio numero casuale.
Quali altri approcci seme ci sono che funzioneranno in un sistema MPI multi-core e saranno ancora unici su ogni core, da correre a correre?
In base alla discussione su http://stackoverflow.com/questions/1554958/how-different-do-random-seeds-need-to-be e l'articolo citato nella risposta, è sufficiente aggiungere il rango all'ora genera numeri non-così-pseudo-casuali perché tutti i semi sarebbero lineari. Ma se solo una pseudo-casuale è accettabile, allora l'approccio time + rank è molto semplice e indipendente dalla piattaforma. – tpg2114