Gcc 什么是内联函数的好启发法?
考虑到您只想优化速度,有什么好的启发式方法可以决定是否内联函数?显然,代码大小应该很重要,但是当(比如)gcc或icc决定是否内联函数调用时,是否还有其他通常使用的因素?在这方面有没有什么重要的学术工作?函数调用意味着一些额外的代码(函数序言,其中设置了新堆栈框架,函数尾声,其中清理了新堆栈框架)。如果您的编译器发现函数代码与序言和尾声相比很小,那么它可以决定不值得进行实际调用,并将函数内联Gcc 什么是内联函数的好启发法?,gcc,gnu,compiler-construction,icc,inlining,Gcc,Gnu,Compiler Construction,Icc,Inlining,考虑到您只想优化速度,有什么好的启发式方法可以决定是否内联函数?显然,代码大小应该很重要,但是当(比如)gcc或icc决定是否内联函数调用时,是否还有其他通常使用的因素?在这方面有没有什么重要的学术工作?函数调用意味着一些额外的代码(函数序言,其中设置了新堆栈框架,函数尾声,其中清理了新堆栈框架)。如果您的编译器发现函数代码与序言和尾声相比很小,那么它可以决定不值得进行实际调用,并将函数内联 我所看到的调用函数而不是内联函数的唯一好处是与大小相关的。我猜内联一个函数然后展开一个循环会导致显著的大
我所看到的调用函数而不是内联函数的唯一好处是与大小相关的。我猜内联一个函数然后展开一个循环会导致显著的大小增加。据我所见,函数大小是编译器用来确定内联的唯一因素。然而,如果您进行概要文件引导优化(PGO),我相信编译器能够使用其他变量,例如调用数/调用设置时间。在.NET中,主要是基于大小。测量父函数和子函数的大小(以编译字节为单位)。然后测量组合函数的大小。如果组合函数较小,那么内联是一个好主意 这样做的原因是可以将尽可能多的代码放入CPU的缓存中。缓存未命中比现代CPU中的函数调用要昂贵得多。维基百科有关于这一点的段落,底部有一些链接:
- 除了内存大小和缓存问题外。从编译器的角度来看,“内联过程中添加的变量可能会消耗额外的寄存器,在寄存器压力已经很高的区域,这可能会导致溢出,从而导致额外的RAM访问。”
- (对于Java)讨论了静态方法和动态加载类的方法内联及其性能改进
- 声称他们的“内联策略基于代码大小和分析信息。如果方法项的执行频率低于某个阈值,则该方法不会内联,因为它被视为冷方法。为了避免代码爆炸,我们不内联字节码大小超过25字节的方法。为了避免沿深度调用链内联,当沿调用链内联字节码的累积大小超过40字节时,内联将停止。“尽管他们有运行时分析信息(方法调用频率),但他们仍然小心避免内联大型函数或函数链以防膨胀
- 有一章介绍编译器设计中的统计和机器学习技术,使用启发式设置各种参数,分析结果。本章参考Vaswani等人的论文,他们在论文中提出“使用经验建模” 为编译器优化构建微体系结构敏感模型的技术”
- (其他一些书从程序员的角度讨论内联,例如,它讨论了过多内联函数的危险以及内联与宏之间的差异。如果编译器可以确定程序员的内联请求弊大于利,那么它们通常会忽略程序员的内联请求;这可以用宏作为替代。)最后的办法。)