在C ++函数中使用内联优化有什么注意事项?

时间:2010-08-22 02:03:01

标签: c++ optimization inline

内联不同类型的功能有什么好处?在开发它们时需要注意哪些问题?我对分析器不是很有用,但是许多不同的算法应用程序似乎可以将速度提高8倍,如果你能提供对我有用的任何指针。

5 个答案:

答案 0 :(得分:5)

内联函数经常被过度使用,后果非常严重。内联向编译器指示可以考虑将函数用于内联扩展。如果编译器选择内联函数,则不会调用该函数,而是将其复制到位。性能增益来自于避免函数调用,堆栈帧操作和函数返回。收益可能相当大。

请注意,他们可以增加程序大小。它们可以通过减少调用者的引用位置来增加执行时间。当大小增加时,调用者的内部循环可能不再适合处理器高速缓存,从而导致不必要的高速缓存未命中以及随之而来的性能损失。内联函数也会增加构建时间 - 如果内联函数发生更改,则必须重新编译世界。一些指导原则:

  • 避免内联函数,直到分析表明哪些函数可以从内联中受益。
  • 在使用和不使用自动内联进行性能分析后,请考虑使用编译器的选项进行自动内联。
  • 只有函数调用开销相对于函数代码较大的内联函数。换句话说,内联调用其他(可能是内联的)函数的大函数或函数并不是一个好主意。

答案 1 :(得分:3)

最重要的指针是,几乎在所有情况下你都应该让编译器做它的事情而不用担心它。

即使您没有声明函数inline,编译器也可以自由地执行函数的内联扩展,即使您声明它inline也可以自由地不执行内联扩展。这完全取决于编译器,这是可以的,因为在大多数情况下,它比在内联扩展函数时知道的要好得多。

答案 2 :(得分:2)

编译器比编程器更好地完成内联工作的原因之一是因为成本/收益权衡实际上是在机器抽象的最低级别决定的:有多少汇编指令组成了你想要内联的函数。考虑典型的非分支汇编指令与函数调用的执行时间之间的比率。这个比率对于机器代码生成器是可预测的,因此编译器可以使用该信息来指导内联。

高级编译器通常会尝试处理内联的另一个机会:当函数B仅从函数A调用而从未从其他地方调用时。这种内联不是出于性能原因(假设A和B不是小函数),而是通过减少需要生成的“函数”总数来减少链接时间。

添加了示例

编译器执行大规模内联(具有大量加速)的一个示例是在STL容器的编译中。 STL容器类被编写为高度通用的,并且作为回报,每个“函数”仅执行一小部分操作。禁用内联时,例如在调试模式下编译时,STL容器的速度会大幅下降。

第二个例子是当被调用者函数包含某些指令时,这些指令要求堆栈在调用者和被调用者之间不受干扰。使用内在函数的SIMD指令会发生这种情况。幸运的是,编译器足够聪明,可以自动内联这些被调用函数,因为它们可以检查是否发出了SIMD汇编指令并内联它们以确保堆栈不受干扰。

底线

除非您熟悉低级分析并且擅长assembly programming/optimization,否则最好让编译器完成这项工作。 STL是一种特殊情况,即使在调试模式下也可以启用内联(使用开关)。

答案 3 :(得分:0)

内联函数的主要好处是可以消除调用开销并允许编译器跨调用边界进行优化。通常,您为优化程序提供的自由度越高,程序执行的效果就越好。

缺点是该功能不再存在。调试器将无法告诉您内部,并且没有外部代码可以调用它。您也无法在运行时替换其定义,因为函数体存在于许多不同的位置。

此外,二进制文件的大小也会增加。

通常,如果函数static没有外部调用者,则应声明它,而不是将其标记为inline。如果你确定没有负面的副作用,只允许函数内联。

答案 4 :(得分:0)

函数调用开销非常小。内联函数的一个更显着的优点是能够直接使用“by reference”变量而无需额外的指针间接。如果参数通过引用传递给简单的变量或字段,那么大量使用通过引用传递的参数的函数可能会受益匪浅。