内联函数有什么好的启发式方法?

时间:2010-01-25 04:46:58

标签: gcc gnu compiler-construction icc inlining

考虑到您只是在尝试优化速度,在决定是否内联函数时,有什么好的启发式方法?显然代码大小应该很重要,但是当(例如)gcc或icc确定是否内联函数调用时,是否还有其他因素?该地区是否有重要的学术工作?

4 个答案:

答案 0 :(得分:8)

维基百科有关于此的a few个段落,底部有一些链接:

  • 除内存大小和缓存问题外,another consideration is register pressure。从编译器的角度来看,内联过程中添加的变量可能会消耗额外的寄存器,并且在寄存器压力已经很高的区域,这可能会导致溢出,从而导致额外的RAM访问。“

JIT编译器和运行时类加载的语言有其他权衡,因为虚拟方法不是静态知道的,但JIT可以收集运行时分析信息,例如方法调用频率:

  • Design, Implementation, and Evaluation of Optimizations in a Just-in-Time Compiler(适用于Java)讨论静态方法和动态加载类的方法内联及其对性能的改进。

  • Practicing JUDO: Java Under Dynamic Optimizations声称他们的“内联策略基于代码大小和分析信息。如果方法条目的执行频率低于某个阈值,则该方法不会内联,因为它是为了避免代码爆炸,我们没有内联一个字节码大小超过25个字节的方法......为了避免沿着深度调用链内联,内联在调用时累积的内联字节码大小停止链超过40个字节。“虽然它们具有运行时分析信息(方法调用频率),但它们仍然小心避免内联大函数或函数链以防止膨胀。

A search on Google Scholar揭示了一些论文,例如

A search on Google Books揭示了很多关于各种情境中函数内联的论文或章节的书籍。

答案 1 :(得分:0)

函数调用意味着一些额外的代码(函数序言,设置新的堆栈帧,以及函数结尾,它被清理)。如果你的编译器发现函数代码与序言和结尾相比较小,那么它可以决定进行实际调用是不值得的,并且会内联函数。

我看到调用函数而不是内联函数的唯一好处是与大小相关。我想内联函数然后展开循环可能会导致显着的大小增加。

答案 2 :(得分:0)

据我所知,函数大小是编译器用于确定内联的唯一因素。但是,如果您进行配置文件引导优化(PGO),我相信编译器能够使用其他变量,例如呼叫数/呼叫建立时间。

答案 3 :(得分:0)

在.NET中主要基于大小。以编译的字节为单位测量父函数和子函数的大小。然后测量组合函数的大小。如果组合函数较小,那么内联是个好主意。

这样做的原因是可以将尽可能多的代码插入CPU的缓存中。缓存未命中比现代CPU中的函数调用要昂贵得多。