2012-01-19 18 views
7

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?

risposta

10

Se date un'occhiata a Random Numbers In Scientific Computing: An Introduction di Katzgrabber (che è un'eccellente e lucida discussione sui dettagli dell'utilizzo dei PRNG per l'elaborazione tecnica), in parallelo suggeriscono di usare una funzione hash di tempo e PID per generare un seme . Dal loro punto 7.1:

long seedgen(void) { 
    long s, seed, pid; 

    pid = getpid(); 
    s = time (&seconds); /* get CPU seconds since 01/01/1970 */ 

    seed = abs(((s*181)*((pid-83)*359))%104729); 
    return seed; 
} 

naturalmente, in Fortran questo sarebbe qualcosa di simile

function seedgen(pid) 
    use iso_fortran_env 
    implicit none 
    integer(kind=int64) :: seedgen 
    integer, intent(IN) :: pid 
    integer :: s 

    call system_clock(s) 
    seedgen = abs(mod((s*181)*((pid-83)*359), 104729)) 
end function seedgen 

E 'anche a volte utile per essere in grado di passare il tempo, piuttosto che chiamare dall'interno seedgen, in modo che, quando si esegue il test, sia possibile fornire valori fissi che generano una sequenza riproducibile (== testabile).

0

L'ora di sistema viene in genere restituita (o almeno facilmente convertita in) un tipo intero: è sufficiente aggiungere il rango del processo al valore e utilizzarlo per inizializzare il generatore di numeri casuali.

+0

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

Problemi correlati