tpg*_*114 7 random parallel-processing multicore seed mpi
两点 - 首先,示例是在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
Run Code Online (Sandbox Code Playgroud)
哪个在我的工作站上运行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
Run Code Online (Sandbox Code Playgroud)
所以,我们通过从中读取种子来克服时钟问题/dev/urandom.这样每个核心都有自己的随机数.
还有哪些种子方法可以在多核MPI系统中运行,并且在每个核心上,从运行到运行仍然是唯一的?
Jon*_*rsi 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;
}
Run Code Online (Sandbox Code Playgroud)
当然,在Fortran中就是这样的
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
Run Code Online (Sandbox Code Playgroud)
它有时也很方便,能够在规定的时间传递,而不是从内部调用它seedgen,这样,当你正在测试你可以把它固定值是然后生成可再现(==可测试)序列.
| 归档时间: |
|
| 查看次数: |
6468 次 |
| 最近记录: |