在Fortran中内联函数

mar*_*trz 2 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
Run Code Online (Sandbox Code Playgroud)

稍后我们只是使用它

foo = binsearch(tab, el)
Run Code Online (Sandbox Code Playgroud)

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

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

为了代码清晰,我不想复制粘贴这个.

jab*_*ali 8

在Fortran中,inlineC中没有直接的类比; 始终由编译器决定哪些函数是内联的.最重要的是编译具有高优化级别的代码以打开积极的内联(例如-Ofast在gfortran中,-fast在ifort中).此外,您可能希望打开"链接时优化"(-flto在gfortran中, -ipo在ifort中),以便编译器可以在链接时根据需要内联不同源文件中的函数.

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

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

  ...
end function
Run Code Online (Sandbox Code Playgroud)

如果你可以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
Run Code Online (Sandbox Code Playgroud)

  • 有什么方法可以验证该函数是否已内联吗? (2认同)
  • 如果您查看地图,如果已内联,则无法找到该功能的地址. (2认同)

小智 4

这取决于编译器。我可以验证这是否适用于 Cray 和 Intel Fortran 编译器,但语句略有不同。

克雷编译器:

!dir$ forceinline :: frob
Run Code Online (Sandbox Code Playgroud)

这将迫使编译器内联函数 frob。您可以将其放置在函数定义的正上方。

英特尔编译器:

!dir$ attributes forceinline :: frob
Run Code Online (Sandbox Code Playgroud)

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

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