2012-01-19 2 views
7

두 가지 - 먼저 예제가 Fortran에 있지만 모든 언어에 대해 보유해야한다고 생각합니다. 두 번째로, 내장 된 난수 생성기는 실제로 무작위가 아니며 다른 생성기가 있지만 우리가하는 일에 사용하는 데 관심이 없습니다.난수 시드의 가능한 소스

랜덤 시드에 대한 대부분의 논의는 프로그램이 런타임에 시드하지 않으면 컴파일 타임에 시드가 생성된다는 것을 인정합니다. 따라서 프로그램을 실행할 때마다 동일한 순서의 숫자가 생성되기 때문에 임의의 숫자에는 적합하지 않습니다. 이것을 극복하는 한 가지 방법은 난수 생성기에 시스템 클럭을 뿌리기위한 것입니다.

그러나 멀티 코어 시스템에서 MPI와 병렬로 실행하면 시스템 클럭 방식으로 동일한 종류의 문제가 발생합니다. 시퀀스가 실행에서 실행으로 변경되는 동안 모든 프로세서는 동일한 시스템 클록을 가지므로 동일한 임의 시드와 동일한 시퀀스를 갖습니다.

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 

2 개 코어 내 워크 스테이션에서 실행하면, 제공 :

그래서 다음 예제 코드를 고려

OLD Rank, dev =   0 0.330676306089146  
OLD Rank, dev =   1 0.330676306089146  
NEW Rank, dev =   0 0.531503215980609  
NEW Rank, dev =   1 0.747413828750221  

을 그래서를, 우리는 /dev/urandom에서 씨앗을 읽어 시계 문제를 극복 대신. 이렇게하면 각 코어가 고유 한 난수를 얻습니다.

멀티 코어 MPI 시스템에서 작동하고 각 코어에서 실행마다 다른 고유 한 접근 방식이있을 수 있습니까?

답변

10

을 Katzgrabber (기술 컴퓨팅을 위해 PRNG 사용에 대한 우수하고 명확한 논의가 있음)에서 살펴보면 병렬로 시간과 PID의 해시 함수를 사용하여 시드를 생성 할 것을 제안합니다 . 자신의 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; 
} 

, 포트란이 또한 오히려 seedgen 내에서 호출보다는 시간에 통과 할 수있는 것이 때로는 편리합니다

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 

같은 것, 그래서 당신이 테스트 할 때 당신은 그것을 재생산 할 수있는 (== testable) 시퀀스를 생성하는 고정 값을 줄 수 있습니다.

0

시스템 시간은 일반적으로 정수 유형으로 반환됩니다 (또는 적어도 쉽게 변환 할 수 있음). 단순히 프로세스 순위를 값에 더하고 난수 생성기를 시드하기 위해 사용합니다.

+0

http://stackoverflow.com/questions/1554958/how-different-do-random-seeds-need-to-be 토론 및 답변에 인용 된 기사를 토대로 시간에 순위 추가하기 모든 씨앗이 선형이기 때문에 의사 - 무작위 수를 생성합니다. 그러나 매우 의사 난수 만 괜찮 으면 시간 + 순위 접근법은 매우 간단하고 플랫폼 독립적입니다. – tpg2114