在fortran中访问虚拟变量会阻止优化?

我正在尝试优化一些fortran代码,并注意到了一些我想理解的惊人行为。 progb的运行速度比proga快3到4倍。唯一的区别是progb中的赋值是“ d = 2”,而不是proga中的赋值是“ d = b”,因此天真的这些应该等效:

  program proga
  implicit  none

  call hist(2)
  stop
  end

  subroutine hist(b)
  implicit  none
  integer,intent(in):: b
  integer   d,i,p(200000000)

  d = b
  do i=1,200000000
     p(i) = i/d
  end do
  write(*,*) p(1)
  end


  program progb
  implicit  none

  call hist(2)
  stop
  end

  subroutine hist(b)
  implicit  none
  integer,p(200000000)

  d = 2
  do i=1,*) p(1)
  end

我用“ gfortran proga.f -O3”进行编译,对于progb同样如此。在Debian的gcc版本4.9.2以及cygwin的gcc版本5.4.0上都会发生这种情况。

当我在不使用-O3标志的情况下进行编译时,两者都以相同的速度运行,因此听起来编译器也无法优化proga。在proga上无法完成哪些优化,为什么?

对于这篇文章,我已经删节了代码(我的实际代码做了一些有用的事情!)。常量200000000应该足够大以提供足够的运行时间。该写操作可以防止循环被优化。

ming870312 回答:在fortran中访问虚拟变量会阻止优化?

值2是一个非常特殊的值。如果编译器知道它总是被2除,它可以移位而不是进行算术运算。但是,在progb中,编译器必须使用任何可能的整数值进行计数,因此必须实现实数除法,而不仅仅是移位。

因此,访问参数不会禁止任何优化。使用固定值可以进行一些特定的优化。尤其是如果是2的幂。

检查https://godbolt.org/z/TcJxYK处的差异

通用版本使用

idiv    ecx

除以2的版本

shr     edx,31
add     eax,edx
sar     eax

idiv指令比移位和加法要慢得多。

对于2的非幂,它仍然是可优化的,但通常还涉及算术运算,例如乘法,加法和减法,而不仅仅是移位。然而,这些比除法要快。除法操作很慢。


如史蒂夫所指出的那样,使用-fwhole-program使编译器可以将所有单元一起编译,并且可以假定它不需要生成不需要的子例程。

顺便说一句,对于我在gfortran上方的Godbolt链接中使用的简化子例程,即使没有-fwhole-program,也会优化对子例程的调用。

本文链接:https://www.f2er.com/3135470.html

大家都在问