Fortran:10个嵌套循环因结束print语句而变慢

时间:2015-08-11 04:58:42

标签: fortran gfortran

我有一些代码可以在大约一秒钟内运行,但在经过非常小的编辑后会慢下来。

以下代码使用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 ,代码总是运行得非常慢。

1 个答案:

答案 0 :(得分:4)

使用gfortan 4.8.3,我发现在包含write语句和删除它们之间没有太多的运行时差异,但-O3-O0之间存在巨大差异。这样做的原因是编译器能够使用-O3大量优化循环,而-O0则不能。编译器基本上可以提前解决问题并完全省略循环。通过更高的优化,编译器还可以使用CPU的更高级功能,这些功能可以更快地运行。

write语句置于循环中有点会破坏编译器积极优化循环的能力,这意味着它不能再完全省略它们,这会导致您看到的运行时间变慢。您可能正在使用较旧版本的gfortran,但这种情况并不能很好地应对。