2015-07-02 59 views
4

我一直在玩各種隨機種子發生器。下面是一個簡單的一個:慢速隨機種子發生器 - 爲什麼?

subroutine init_random_seed() 
    integer :: i, n, clock 
    integer, dimension(:), allocatable :: seed 
    call random_seed(size = n) 
    allocate(seed(n)) 
    call system_clock(count=clock) 
    seed = clock + 37 * (/ (i - 1, i = 1, n) /) 
    call random_seed(put = seed) 
    deallocate(seed) 
end 

...和更強大的一個:

SUBROUTINE init_random_seed() 
    USE ISO_Fortran_env, ONLY: INT64 
    IMPLICIT NONE 
    INTEGER, ALLOCATABLE :: seed(:) 
    INTEGER :: i, n, un, istat, dt(8), pid 
    INTEGER(INT64) :: t 
    CALL RANDOM_SEED(size = n) 
    ALLOCATE(seed(n)) 
    OPEN(newunit=un, file='/dev/urandom', access='stream', status='old', action='read', form='unformatted', iostat=istat) 
    IF (istat == 0) THEN 
    READ(un) seed 
    CLOSE(un) 
    ELSE 
    CALL SYSTEM_CLOCK(t) 
    IF (t == 0) THEN 
     CALL DATE_AND_TIME(values = dt) 
     t = (dt(1) - 1970) * 365_INT64 * 24 * 60 * 60 * 1000 + dt(2) * 31_INT64 * 24 * 60 * 60 * 1000 + dt(3) * 24_INT64 * 60 * 60 & 
     * 1000 + dt(5) * 60 * 60 * 1000 + dt(6) * 60 * 1000 + dt(7) * 1000 + dt(8) 
    END IF 
    pid = GETPID() 
    t = IEOR(t, INT(pid, KIND(t))) 
    DO i = 1, n 
     seed(i) = lcg(t) 
    END DO 
    END IF 
    CALL RANDOM_SEED(put = seed) 
    DEALLOCATE(seed) 
CONTAINS 
    FUNCTION lcg(s) 
    INTEGER :: lcg 
    INTEGER(INT64) :: s 
    IF (s == 0) THEN 
     s = 104729 
    ELSE 
     s = MOD(s, 4294967296_INT64) 
    END IF 
    s = MOD(s * 279470273_INT64, 4294967291_INT64) 
    lcg = INT(MOD(s, INT(HUGE(0), INT64)), KIND(0)) 
    END FUNCTION lcg 
END SUBROUTINE init_random_seed 

第二個生成更高質量的隨機數,但是速度比較慢。有沒有人看到爲什麼?

+1

你的問題是合理的,但無論如何:爲什麼會有人關心這個速度?你應該只稱它一次,否則不好的事情發生。 –

回答

1

第二個子程序正在執行很多比第一個更多的algebriac操作。另外,第二個子程序通過撥打OPEN來完成文件I/O。這可能是性能殺手。從磁盤讀取通常比從存儲器讀取要慢幾個數量級。您可以嘗試對OPEN進行註釋,將其替換爲硬編碼值,然後再次對兩個子例程進行基準測試。