我有一些代码可以在大约一秒钟内运行,但在经过非常小的编辑后会慢下来。
以下代码使用gfortran -O3
在1秒内运行 program loop
implicit none
integer n, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10
parameter(n=18) !<=== most important
integer i,array(n)
real cal
real p1(n)
do i=1,n
p1(i)=float(i)/10.
enddo
write (*,1) p1
1 format (10(f6.2))
cal=0.
i1=0
i2=0
do i1=1,n
!write(*,1) cal !<-- too slow if write here
do i2=1,n
do i3=1,n
do i4=1,n
do i5=1,n
do i6=1,n
do i7=1,n
do i8=1,n
do i9=1,n
do i10=1,n
cal=p1(i1) !<-- perfectly happy to compute, as long as I don't write
array(i1)=i1+i2
enddo
enddo
enddo
enddo
enddo
enddo
enddo
enddo
enddo
!write(*,1) cal !<-- and too slow if write here too!
enddo
write(*,*) (array(i),i=1,n)
stop
end
首先,请原谅我f77&amp;的混合物。 90.这是一个基于真实问题的简单例子。然而,重点是,如果参数 n = 17 ,一切都很好。倒数第二个写语句可以取消注释,代码运行大约一秒钟。但是,当n = 18时,代码会慢慢停止...除非,如果倒数第二个写入语句被注释掉,它会在 n = 18 的情况下运行一秒钟。
在两个测试中,总共有 17 ^ 10 和 18 ^ 10 次迭代。我一直无法找到任何迹象表明总迭代次数有限制。我一直在想18 ^ 10必须超过一些限制,但我不知道是什么。为什么打印声明对 n = 18 而不是 n = 17 很重要?更多信息:内存使用率几乎为零。 CPU是i5-4570 CPU @ 3.20GHz 。
如果我使用 -O0 ,代码总是运行得非常慢。
答案 0 :(得分:4)
使用gfortan 4.8.3,我发现在包含write
语句和删除它们之间没有太多的运行时差异,但-O3
和-O0
之间存在巨大差异。这样做的原因是编译器能够使用-O3
大量优化循环,而-O0
则不能。编译器基本上可以提前解决问题并完全省略循环。通过更高的优化,编译器还可以使用CPU的更高级功能,这些功能可以更快地运行。
将write
语句置于循环中有点会破坏编译器积极优化循环的能力,这意味着它不能再完全省略它们,这会导致您看到的运行时间变慢。您可能正在使用较旧版本的gfortran,但这种情况并不能很好地应对。