c++;估计函数内联效益的启发式方法 在C++中,什么是一个好的启发式算法来估计函数内联的计算时间效益,特别是当函数被频繁调用时,占程序执行时间的10%=(如蛮力或随机优化过程的评价函数)。尽管内联最终可能超出我的控制范围,但我仍然很好奇。

c++;估计函数内联效益的启发式方法 在C++中,什么是一个好的启发式算法来估计函数内联的计算时间效益,特别是当函数被频繁调用时,占程序执行时间的10%=(如蛮力或随机优化过程的评价函数)。尽管内联最终可能超出我的控制范围,但我仍然很好奇。,c++,optimization,inlining,C++,Optimization,Inlining,某些体系结构上的函数调用和返回每个只需要一条指令(尽管它们通常不像RISC那样是单周期指令)。通常,您可以将其与函数体表示的周期数进行比较。一个简单的属性访问可能只是一条指令,因此将它放入一个非内联函数将使执行它的指令数量增加三倍——显然,内联是一个很好的选择。另一方面,格式化字符串以进行打印的函数可能代表数百条指令,因此再多两条指令也不会有任何区别。此处的行为在某种程度上取决于编译器。显然,对于递归函数,内联行为在理论上是无限的。“inline”关键字只是对编译器的一个提示,如果不能使用它,它

某些体系结构上的函数调用和返回每个只需要一条指令(尽管它们通常不像RISC那样是单周期指令)。通常,您可以将其与函数体表示的周期数进行比较。一个简单的属性访问可能只是一条指令,因此将它放入一个非内联函数将使执行它的指令数量增加三倍——显然,内联是一个很好的选择。另一方面,格式化字符串以进行打印的函数可能代表数百条指令,因此再多两条指令也不会有任何区别。

此处的行为在某种程度上取决于编译器。显然,对于递归函数,内联行为在理论上是无限的。“inline”关键字只是对编译器的一个提示,如果不能使用它,它可以选择忽略它。有些编译器将递归函数内联到一定的深度


至于“这将加快多少速度”——不幸的是,我们无法提供任何关于这个问题的答案,因为“这取决于”——函数做了多少工作,而函数调用机制本身的开销又是多少。为什么不设置一个测试并查看?

如果您的瓶颈在递归函数中,并且假设递归的级别不是最小的(即平均递归不只是几个级别),那么最好在函数中使用算法,而不是使用内联

如果可能的话,尝试将递归转换为循环或尾部递归(编译器可以隐式地将其转换为循环),或者尝试确定在函数中花费成本的位置。尽量减少内部操作的影响(可能您正在动态分配可能具有自动存储持续时间的内存,也可能您可以在包装器中考虑在函数外部执行的常见操作,并将其作为额外参数传入,…)

*在注释之后编辑,说明递归不是有意的,而是迭代*


如果编译器可以访问函数的定义,那么在大多数情况下,它将为您做出正确的决定。如果它没有访问定义的权限,只需移动代码就可以看到它。可以将函数设置为
静态
函数,以提供一个额外的提示,表明它不会在其他任何地方使用,或者甚至将其标记为
内联
(知道这不会强制内联),但避免使用将强制内联的特殊属性,因为编译器可能比不看代码就能产生的任何简单启发式方法做得更好。

没有一般的答案。这取决于硬件、数量和成本 它的参数类型,以及在函数中执行的操作。多久一次 它叫什么名字,在哪里。例如,在Sparc上,参数(和 返回值)传递到寄存器中,每个函数得到16个新值 寄存器:如果函数足够复杂,这些新寄存器可能会 避免函数内联时可能发生的溢出,并且 非内联版本可能会比内联版本更快。根据情报, 这是寄存器差,并在寄存器中传递参数,只是 相反,对于同一程序中的同一函数,可能是正确的。更多 通常,内联可能会增加程序大小,减少局部性。或 对于非常简单的函数,它可以减少程序大小;但这一次 取决于架构。唯一可能知道的方法就是尝试 两者都是,测量时间。即使这样,你也只能知道
具体的程序,在那个特殊的硬件上。

我们的经验,20年的C++计算密集型写作是内联不是银弹。您确实需要分析您的代码,以查看内联是否会提高性能。对于我们来说,除了低级的2D和3D点和向量操作,内联是浪费时间。与尝试微观管理时钟信号相比,制定一个更好的算法要好得多。

内联为您节省的所有成本都是函数的进入/退出成本,因此只有当函数几乎什么都不做时才值得考虑。 当然,如果函数本身包含函数调用,则可能不值得考虑


即使函数做的很少,它也必须被调用,以至于在函数的任何加速之前,它拥有程序计数器的时间占相当大的百分比。

如果它是递归调用的,那么它就不能完全内联(除非递归是静态有界的,但很难检测到)。你知道你可以使用
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
(GCC)或
\uu。仔细阅读尾部呼叫。但即使是非尾部递归函数有时也可以自动重构和内联。@Konrad:如果执行了尾部递归优化,则递归已隐式内联,因此尝试内联外部调用没有意义(除非成本与递归无关,而是每个递归级别的成本问题,或者递归级别最小)@康斯坦丁尼乌斯:Dong so通常会适得其反。编译器在决定何时内联方面比人类好得多。强制编译器通常会导致次优代码。调用需要如此少的指令的可能性有多大,有没有办法猜测特定函数需要多少指令?你必须(1)了解足够的汇编语言,大致了解函数的工作原理