Random PGI Fortran中的随机数生成器不太随机
以下代码仅生成一个简单的三重随机数:Random PGI Fortran中的随机数生成器不太随机,random,fortran,fortran90,gfortran,pgi,Random,Fortran,Fortran90,Gfortran,Pgi,以下代码仅生成一个简单的三重随机数: program testrand integer, parameter :: nz = 160, nf = 160, nlt = 90 real :: tmpidx(3) integer :: idxarr(3), idx1, idx2, idx3, seed_size, ticks integer, allocatable :: seed(:) call random_seed(size=seed_size) allocate(seed(seed_s
program testrand
integer, parameter :: nz = 160, nf = 160, nlt = 90
real :: tmpidx(3)
integer :: idxarr(3), idx1, idx2, idx3, seed_size, ticks
integer, allocatable :: seed(:)
call random_seed(size=seed_size)
allocate(seed(seed_size))
call system_clock(count=ticks)
seed = ticks+37*(/(i-1, i=1,seed_size)/)
call random_seed(put=seed)
deallocate(seed)
call random_number(tmpidx)
idxarr = tmpidx * (/nz, nf, nlt/)
idx1 = max(1,idxarr(1))
idx2 = max(1,idxarr(2))
idx3 = max(1,idxarr(3))
print *,idx1, idx2, idx3
end program
我用gfortran编译了这个,运行了几次,我得到:
> gfortran testrand.f90
> ./a.out
74 98 86
> ./a.out
113 3 10
> ./a.out
44 104 27
看起来很随意。现在我使用PGI Fortran编译并运行了几次:
> pgf90 testrand.f90
> ./a.out
1 1 1
> ./a.out
1 1 1
> ./a.out
1 1 1
当然,没有办法完全确定,但我怀疑这不是随机的有人知道这是怎么回事吗?有人知道使用PGI Fortran获取随机数的正确方法吗?不知何故,PGI并不像GNU编译器那样实现系统时钟。我不知道为什么,我最近通过做类似于你的事情发现了它 要了解我在说什么,只需在调用
system\u clock
后打印ticks
。很有可能,使用PGI和GNU编译器,您会一直得到0
。为了解决您的问题,您可以修改下面的代码。这是一个稍加修改的代码版本,您可以在
程序测试
仅使用iso_fortran_env:int64
整数,参数::nz=160,nf=160,nlt=90
real::tmpidx(3)
整数::idxarr(3)、idx1、idx2、idx3、种子大小、刻度
整数,可分配::种子(:)
调用随机种子(大小=种子大小)
分配(种子(种子大小))
! 呼叫系统时钟(计数=滴答声)
! 种子=蜱+37*(/(i-1,i=1,种子大小)/)
! 调用随机种子(put=seed)
!
! 解除分配(种子)
调用init_random_seed()
呼叫随机号码(tmpidx)
idxarr=tmpidx*(/nz,nf,nlt/)
idx1=最大值(1,idxarr(1))
idx2=最大值(1,idxarr(2))
idx3=最大值(1,idxarr(3))
打印*,idx1,idx2,idx3
包含
!
子例程init_random_seed()
隐式无
整数,可分配::种子(:)
整数::i,n,istat,dt(8),pid
整数(int64)::t
整数,参数::un=703
调用随机种子(大小=n)
分配(种子(n))
! 如果操作系统提供随机数生成器,请首先尝试
打开(unit=un,file=“/dev/uradom”,access=“stream”&
form=“未格式化”,action=“读取”,status=“旧”,iostat=istat)
如果(istat==0),则
读取(联合国)种子
关闭(联合国)
其他的
! PID是
! 在一个启动相同的多个实例时非常有用
! 并行编程。
呼叫系统时钟(t)
如果(t==0),则
调用日期和时间(值=dt)
t=(dt(1)-1970)*365*64*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)
如果结束
pid=getpid()
t=ieor(t,int(pid,种类(t)))
i=1,n吗
种子(i)=lcg(t)
结束
如果结束
调用随机种子(put=seed)
!打印*,“最佳种子=”,种子
结束子例程init_random_seed
!
功能lcg(s)
整数::lcg
整数(int64),意图(输入输出)::s
如果(s==0),则
s=104729
其他的
s=mod(s,4294967296_int64)
如果结束
s=mod(s*279470273_int64,4294967291_int64)
lcg=int(mod(s,int(巨大的(0),8)),种类(0))
端功能液晶显示器
!
!此选项特别用于pgf90,以提供getpid()函数
!> @返回当前进程的进程ID
!! @todo编写实际代码,目前返回一个固定值
!<
函数getpid()结果(pid)
整数pid
pid=53!只是一个素数,没有特殊意义
结束函数getpid
结束程序
Ack!我已经看到了,我希望避免它!永远不要忘记日期和时间()似乎效果更好。谢谢
program testrand
use iso_fortran_env, only: int64
integer, parameter :: nz = 160, nf = 160, nlt = 90
real :: tmpidx(3)
integer :: idxarr(3), idx1, idx2, idx3, seed_size, ticks
integer, allocatable :: seed(:)
call random_seed(size=seed_size)
allocate(seed(seed_size))
! call system_clock(count=ticks)
! seed = ticks+37*(/(i-1, i=1,seed_size)/)
! call random_seed(put=seed)
!
! deallocate(seed)
call init_random_seed()
call random_number(tmpidx)
idxarr = tmpidx * (/nz, nf, nlt/)
idx1 = max(1,idxarr(1))
idx2 = max(1,idxarr(2))
idx3 = max(1,idxarr(3))
print *,idx1, idx2, idx3
contains
!
subroutine init_random_seed()
implicit none
integer, allocatable :: seed(:)
integer :: i, n, istat, dt(8), pid
integer(int64) :: t
integer, parameter :: un=703
call random_seed(size = n)
allocate(seed(n))
! First try if the OS provides a random number generator
open(unit=un, file="/dev/urandom", access="stream", &
form="unformatted", action="read", status="old", iostat=istat)
if (istat == 0) then
read(un) seed
close(un)
else
! The PID is
! useful in case one launches multiple instances of the same
! program in parallel.
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)
!print*, "optimal seed = ", seed
end subroutine init_random_seed
!
function lcg(s)
integer :: lcg
integer(int64), intent(in out) :: 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), 8)), kind(0))
end function lcg
!
!this option is especially used for pgf90 to provide a getpid() function
!> @brief Returns the process ID of the current process
!! @todo write the actual code, for now returns a fixed value
!<
function getpid()result(pid)
integer pid
pid = 53 !just a prime number, no special meaning
end function getpid
end program