2012-08-23 40 views
2

我有一个Fortran代码是这样的:FORTRAN - Reduce函数调用的开销

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 

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

回答

5

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

+0

对于这种情况,所有的参数都是只读的,所以我应该将它们全部标记为“intent(in)'?但是通过指定'intent(in)'我会得到什么样的性能增益?我正在用'-O3 flag'编译最高优化。另外'纯'做什么? – arunmoezhi

+1

pure告诉编译器该函数没有副作用,是的,标记所有参数意图(in)表示在函数期间没有任何变化。并且请注意,-O3不会启用* all *优化;检查你的编译器手册页,看看是否有任何额外的优化标志可能与这种情况有关。 –

+0

我搜索了'pure'并得到了相同的解释。 '纯功能没有副作用'。但是'副作用'在这里意味着什么。除了'-O3'之外,我正在使用'-ipo',因为这个函数在另一个源文件中。 – arunmoezhi

2

过程调用的开销通常很低。如果函数有30行代码,可能会得到很少的收益,因为实际函数将占据函数调用的主导地位。如果你想确定,测量当前实现的运行时间,然后内联代码并测量运行时间。

+2

我不能完全同意。昨天我与gfortran一起奋斗,没有将同一中间体的6行元素函数嵌入三重循环。成本是巨大的。我结束了一个声明函数。当然,我使用O5,finline-functoons和flto。 –

+1

@VladimirF:什么可能是不内联6行函数的原因? 即使我有这样的问题。我在一个不同的源文件中有一个30行函数,并且使用'-finline-limit = 500'和'-O3'标志,但仍然没有内联。但是当我使用'-ipo'时,它被内联了,我得到了1.5倍的性能提升。 – arunmoezhi

+1

@arunmoezhi,内联默认限制在同一翻译单元中的子例程。 '-ipo'告诉编译器也查看可能的跨单元优化,但会显着减慢编译和/或可能破坏代码,因此默认关闭。 –