2点 - 最初の例はFortranですが、どの言語にも当てはまるはずです。第2に、組み込みの乱数ジェネレータは本当にランダムではなく、他のジェネレータも存在しますが、私たちが行っていることにそれらを使用することには興味がありません。乱数シードの可能なソース
ランダムシードに関する多くの議論では、プログラムが実行時にそれをシードしないと、コンパイル時にシードが生成されることを認識しています。したがって、プログラムが実行されるたびに同じ番号のシーケンスが生成されますが、これは乱数には適しません。これを克服する1つの方法は、乱数ジェネレータにシステムクロックを設定することです。
しかし、マルチコアマシン上でMPIと並行して実行すると、システムクロックのアプローチによって同じ種類の問題が発生しました。シーケンスは実行ごとに変わりましたが、すべてのプロセッサは同じシステムクロックを持ち、同じランダムシードと同じシーケンスを持っていました。
したがって、次のコード例で考えてみます。だから、
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
から種子を読み取ることによって、クロックの問題を克服:与え、2つのコアで私のワークステーション上で実行
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
を代わりに。このようにして、各コアは独自の乱数を取得します。
マルチコアのMPIシステムでも動作し、実行ごとに各コアで一意になる他のシードアプローチはありますか?
http://stackoverflow.com/questions/1554958/how-different-do-random-seeds-need-to-beに関するディスカッションとその回答に引用された記事に基づいて、ランクを時間に追加するだけですすべてのシードが線形であるため、擬似乱数を生成します。しかし、擬似乱数のみが問題ない場合は、時間+順位のアプローチは非常に簡単でプラットフォームに依存しません。 – tpg2114