FORTRAN - 减少函数调用开销

Posted

技术标签:

【中文标题】FORTRAN - 减少函数调用开销【英文标题】:FORTRAN - Reduce function call overhead 【发布时间】:2012-08-23 01:02:24 【问题描述】:

我有一个这样的 fortran 代码:

file1.f90

program myprog
 use func1mod
    do i=1,N
       call subroutine1
    enddo
    subroutine subroutine1
         integer*8::var1,var2,var3,...
         do j=1,N
            x=func1(var1,var2,var3,..)
            computations based on x
         enddo
    return
    end
end 

file2.f90

 module func1mod
 contains
     func1(var1,var2,var3,....)
         func1=some computations based on var1, var2, var3, ...
      return
     end function func1
 end module func1mod

function func1 不会修改它的任何参数。它根据参数计算一个值并返回一个值。 # of arguments 很大,但函数少于 30 行代码。减少函数调用开销的最佳方法是什么。 一种方法是内联函数。还有其他出路吗?

【问题讨论】:

【参考方案1】:

您能做的最好的事情就是尽可能明确地说明函数的语义,尽可能提高优化,并让编译器就如何最好地实现调用做出最佳决策。确保虚拟变量标记为intent(in),并将函数标记为pure - 尽管如果它只有 30 行,编译器无疑会在高度优化时注意到这些东西 - 并检查你的编译器选项,看看你是否有任何东西可以这样做来鼓励(例如)内联。

【讨论】:

在这种情况下,所有参数都是只读的,所以我应该将它们都标记为intent(in)吗?但是通过指定intent(in) 我将获得什么性能提升?我正在使用-O3 flag 进行最高优化编译。还有pure 是做什么的? pure 告诉编译器该函数没有副作用,是的,标记所有参数 intent(in) 表示在函数期间不会发生任何变化。请注意 -O3 不会开启 all 优化;检查您的编译器手册页,看看是否有任何其他优化标志可能与这种情况相关。 我搜索了pure 并得到了相同的解释。 pure function has no side effects。但是side effects 在这里是什么意思。除了-O3,我使用的是-ipo,因为这个函数在不同的源文件中。 @arunmoezhi - 函数的“无副作用”意味着该函数除了通过其结果之外不会更改程序的状态 - 它不会修改其参数,它不会做 IO,不改变模块变量或共同变量。 PURE 程序对它们有许多特定的限制(所有这些都是约束),这意味着它们不会产生副作用。但请注意,一个程序“实际上”没有副作用才能被提名为纯程序是不够的 - 它必须满足所有特定限制。 轶事:删除 pure 关键字实际上将速度提高了 2 倍,在我的例子中是 gfortran。我的猜测是gfortran 无法弄清楚它可以避免不必要的分配+复制。 >_>【参考方案2】:

通常,过程调用的开销很低。如果函数有 30 行代码,您可能会获得很少的收益,因为实际函数将支配函数调用。如果您想确定,请测量当前实现的运行时间,然后内联代码并测量该运行时间。

【讨论】:

我不能完全同意。昨天我在 gfortran 上苦苦挣扎,它没有将 6 行元素函数从同一个 midule 内联到三重循环中。代价是巨大的。我最终得到了一个声明函数。当然我用过 O5、finline-functoons 和 flto。 @VladimirF:不内联 6 行函数的原因可能是什么?甚至我也有这样的问题。我在不同的源文件中有一个 30 行函数,并使用了 -finline-limit=500-O3 标志,但它仍然没有内联。但是当我使用 -ipo 时,它被内联了,我得到了 1.5 倍的性能提升。 @arunmoezhi,默认情况下,内联仅限于同一翻译单元中的子例程。 -ipo 告诉编译器还要查看可能的跨单元优化,但会显着减慢编译速度和/或可能破坏代码,因此默认情况下是关闭的。 @HristoIliev:再次感谢您来救我 :) 需要对您的建议进行一些澄清。同一个翻译单元是什么意思? it could break the code 是什么意思? @arunmoezhi,相同的翻译单元通常意味着相同的源文件,因为编译器通常一次解析一个源文件。在某些情况下,使用数值不稳定的算法可能会破坏代码。此外,我遇到过一些情况,其中-ipo 与英特尔的编译器导致了神秘的链接错误......

以上是关于FORTRAN - 减少函数调用开销的主要内容,如果未能解决你的问题,请参考以下文章

从 Fortran 调用 C 函数,其中 C 函数名称最初是从 C 传入的

C语言调用Fortran

Fortran 调用 C:如何获得有效的矢量化函数

用于从 FORTRAN 代码调用的 C++ 函数调用 C++ 代码的 Cmake 配置文件

fortran调用 带有参数 且 返回类型为数组的函数 及 相关歧义分析

fortran调用 带有参数 且 返回类型为数组的函数 及 相关歧义分析