在Fortran

时间:2017-02-22 08:18:50

标签: fortran inline

在Fortran项目中,我们使用二进制搜索来查找所需的值:

integer function binsearch(tab, el)
  implicit none

  real, intent(in) :: tab(:), el
  integer :: a, b, mid

  a = 1
  b = size(tab)

  do while (b - a > 1)
    mid = (a + b)/2
    if (el >= tab(mid)) then
      a = mid
    else
      b = mid
    endif
    ! if (el < tab(mid + 1)) exit ! BAD OPTIMIZATION !
  enddo

  binsearch = a
end function binsearch

稍后我们只是使用它

foo = binsearch(tab, el)

不幸的是,周围的例程被大量使用,BAD OPTIMIZATION将总执行时间提高了一半。所以我考虑了内联函数来降低通话费用。

是否有可能将此功能标记为内联?在C中有关键字inline这是对编译器的建议 - 在Fortran 2008中是否有这样的东西?

我不想为了代码清晰度而复制粘贴它。

2 个答案:

答案 0 :(得分:6)

在Fortran中,与C中的inline没有直接的类比;始终由编译器决定哪些函数是内联的。最重要的是编译具有高优化级别的代码以启用积极内联(例如,gfortran中的-Ofast,ifort中的-fast。此外,您可能希望启用&#34;链接时优化&#34; (-flto在gfortran中,-ipo在ifort中),以便编译器可以在链接时在必要时内联来自不同源文件的函数。

但是,有一些方法可以重写代码,增加内联的机会。一种方法是将函数显式标记为pure(即没有副作用的函数),因为这样的含义使编译器更容易优化对它的调用。换句话说:

pure function binsearch(tab, el) result(r)
  real, intent(in) :: tab(:), el
  integer          :: r, a, b, mid

  ...
end function

如果您可以将binsearch重写为您使用它的任何函数内的嵌套函数,则编译将很可能通过函数替换函数调用tab即使您没有更改编译选项,也可以使用正文或快速goto语句。在那种情况下:

subroutine some_other_thing()
  ...

  ! Do the search
  i = binsearch(tab, el)

  ...

contains
  pure function binsearch(tab, el) result(r)
    real, intent(in) :: tab(:), el
    integer          :: r, a, b, mid

    ...
  end function
end subroutine

答案 1 :(得分:2)

这取决于编译器。我可以验证这适用于Cray和英特尔Fortran编译器,但声明略有不同。

Cray编译器:

!dir$ forceinline :: frob

这会强制编译器内联函数frob。你将它放在函数定义的正上方。

英特尔编译器:

!dir$ attributes forceinline :: frob

我没有看到gcc / gfortran目前有这些选项。

两个编译器上的手册都涵盖了这一点。