我无法理解的Fortran计时问题

时间:2017-11-30 22:32:04

标签: fortran gfortran

我(在我的理论物理数值方法课上)写了一个非常简单的随机漫步程序,在维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秒!?

怎么可能?

1 个答案:

答案 0 :(得分:1)

这是一个非常典型的观察事项。人们在创建人工计算时只会测试性能并且不会创建有用的结果。如果未打印结果,编译器可以识别出它不需要程序输出的结果,并且可能完全省略计算。

要检查它,您可以添加-fdump-tree-optimized标志以获取名为GIMPLE的特殊源表单,并且可以比较源代码的这两个变体的输出。它将输出写入名为yourfilename.f90.something.optimized的文件。我确实可以看到很大一部分缺失。基本上整个r2数组及其操作都经过优化。如果您更了解,也可以比较生成的程序集。