我无法理解的 Fortran 时间问题

A fortran timing issue I cannot understand

我(为理论物理数值方法中的 class)编写了一个非常简单的 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 列:第一列是 "time"(步数)的对数,第二列是到原点的平均平方距离的对数。第二列 "on average" 应与第一列相同。到目前为止一切顺利,程序运作良好,结果非常合理。但这里的问题;在我的 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秒!?

怎么可能?

这是一个很典型的现象。人们在创建仅测试性能而不会创建有用结果的人工计算时遇到了这个问题。当不打印结果时,编译器可以识别它不需要程序输出的结果,可以完全省略计算。

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