我(在我的理论物理数值方法课上)写了一个非常简单的随机漫步程序,在维2中。这是:
program random_walk
implicit none
integer, parameter :: Nwalker = 1000000
integer, parameter :: Nstep = 100
integer, parameter :: Nmeas = 10
integer :: posx, posy, move
integer :: is, im, iw
real :: start_time, stop_time
double precision, dimension(Nmeas) :: dist, r2
real :: rnd
do im = 1, Nmeas
dist(im) = im*Nstep
r2(im) = 0.0
end do
call cpu_time(start_time)
do iw = 1, Nwalker
posx = 0
posy = 0
do im = 1, Nmeas
do is = 1, Nstep
call random_number(rnd)
move = 4*rnd
if (move == 0) posx = posx + 1
if (move == 1) posy = posy + 1
if (move == 2) posx = posx - 1
if (move == 3) posy = posy - 1
end do
r2(im) = r2(im) + posx**2 + posy**2
end do
end do
r2 = r2 / Nwalker
call cpu_time(stop_time)
do im = 1, Nmeas
print '(f8.6, " ", f8.6)', log(dist(im)), log(r2(im))
end do
print '("Time = ", f6.3, " seconds")', stop_time - start_time
end program
最后它应该打印10行2列:第一列是“时间”(步数)的对数,第二列是距离原点的平均平方距离的对数。第二列“平均”应该等于第一列。到目前为止一切顺利,该方案运作良好,结果非常合理。但这里的问题;在我的macbookpro(2,7 GHz Intel Core i7,编译器gfortran 7.1.0,优化-O2)上运行平均花费超过20秒。但如果我注释掉这些内容:
! do im = 1, Nmeas
! print '(f8.6, " ", f8.6)', log(dist(im)), log(r2(im))
! end do
超出“stop_time”计算,结果是运行时间...不到6秒!?
怎么可能?
答案 0 :(得分:1)
这是一个非常典型的观察事项。人们在创建人工计算时只会测试性能并且不会创建有用的结果。如果未打印结果,编译器可以识别出它不需要程序输出的结果,并且可能完全省略计算。
要检查它,您可以添加-fdump-tree-optimized
标志以获取名为GIMPLE的特殊源表单,并且可以比较源代码的这两个变体的输出。它将输出写入名为yourfilename.f90.something.optimized
的文件。我确实可以看到很大一部分缺失。基本上整个r2
数组及其操作都经过优化。如果您更了解,也可以比较生成的程序集。