C++ 宏是强制内联的唯一方法吗
我有一个类成员函数,它是我的应用程序中的关键路径。我的应用程序必须以尽可能快的速度交付预期的(而不是期望的)总体性能 该函数相当复杂,但具有重复多次的几乎相同的部分。比如:C++ 宏是强制内联的唯一方法吗,c++,c++14,C++,C++14,我有一个类成员函数,它是我的应用程序中的关键路径。我的应用程序必须以尽可能快的速度交付预期的(而不是期望的)总体性能 该函数相当复杂,但具有重复多次的几乎相同的部分。比如: if (condition) { //... some code } if (another condition} { //... nearly identical code which may change condition } if (condition) { //... some code (
if (condition)
{
//... some code
}
if (another condition}
{
//... nearly identical code which may change condition
}
if (condition)
{
//... some code (same as above)
}
// and so on
为了使代码更易于阅读、理解和维护,我喜欢将其分解并使用函数调用。比如:
if (condition)
{
some_function(some_param);
}
if (another condition}
{
some_function(some_other_param);
}
if (condition)
{
some_function(some_param);
}
我负担不起调用函数的任何开销,因此我喜欢确保某些函数
始终是内联的
我搜索了这么多,读了几篇讨论类似问题的帖子,但内容并不完全相同。这些帖子表明唯一的方法是宏
我讨厌使用宏
,但另一方面,我也讨厌当前函数的复杂性。这就像是在两种邪恶之间做出选择
是这样吗?宏是实现这一点的唯一方法吗
更新
我得到了很多好的反馈(谢谢)
几乎所有的答案都表明,我不必担心/关心强制函数调用内联,因为编译器无论如何都会为我做得最好
所以我决定试试,做个测试。我重写了代码,以便在可以重用代码片段时使用函数调用,并最终得到更可读(和可维护)的版本
然后,我用100次测试运行测试了新代码和旧代码,并计算了平均性能。平均而言,新版本的性能比旧代码低约1%(略低于..0.88%)。所以有一个性能的打击。另一方面,表演命中率没有我预期的那么高
我的结论是,我更喜欢新代码,因为它更容易理解。这也意味着更容易维护、调试和移交给其他人。然后,我将不得不通过在其他代码块中的增益来找到丢失的性能
哦,最后一件事——接受哪个答案?我真的不知道。所有答案都是有用的输入。但实际上只有两个答案解决了最初的问题。对我来说,它们似乎同样好,所以我将首先使用发布的一个。嗯,宏将是获得内联代码的唯一保证方式
也可以使用
您应该尝试编译
内联
函数,然后检查生成的代码,看看编译器是否内联了函数调用。好吧,宏是获得内联代码的唯一保证方法
也可以使用
您应该尝试编译
内联
函数,然后检查生成的代码,看看编译器是否内联函数调用您。编译器在决定是否内联候选函数时使用评分技术。inline
关键字对该分数的影响很小。对于gcc,有许多命令行选项可以调整评分:
-finline-limit
-fmax-inline-insns-single
-fmax-inline-insns-auto
我的建议是,如上所述,首先看看编译器是否在内联函数。如果是,就离开它。编译器擅长这一点,只有当您没有得到想要的东西时,才应该进行干预。如果不是,并且您正在使用gcc,那么接下来可以尝试调整上述选项
如果这些都不起作用,那么回答您的问题,是的,宏是强制内联的唯一方法,即使在具有
\uu forceinline
的MSVC上也是如此。即便如此,也要尽一切可能避免使用它们。编译器在决定是否内联候选函数时使用评分技术。inline
关键字对该分数的影响很小。对于gcc,有许多命令行选项可以调整评分:
-finline-limit
-fmax-inline-insns-single
-fmax-inline-insns-auto
我的建议是,如上所述,首先看看编译器是否在内联函数。如果是,就离开它。编译器擅长这一点,只有当您没有得到想要的东西时,才应该进行干预。如果不是,并且您正在使用gcc,那么接下来可以尝试调整上述选项
如果这些都不起作用,那么回答您的问题,是的,宏是强制内联的唯一方法,即使在具有
\uu forceinline
的MSVC上也是如此。即便如此,还是要尽一切可能避免使用它们。信不信由你,有时函数调用比内联代码更快
因此,我建议编写函数时,编译器可以在if
语句的调用点看到函数体,可以选择将函数标记为内联,然后让编译器确定是否最好内联调用
然后,您要做的是分析代码(或者可能检查生成的程序集),并查看热点在哪里。如果它特别显示对函数的调用是热的,那么您必须求助于宏方法。请注意,如果您确实使用宏,请确保再次配置文件,并且它确实有帮助。编译器在优化方面越来越在行。信不信由你,有时函数调用比内联代码更快 因此,我建议以这样的方式编写函数:
cmp n, 1
bne end_if_1
mov 2, n
// ...
end_if_1:
cmp y, 1
bne end_if_2
// result of 200 lines of cod
cmp n, 1
bne end_if_1
mov 2, n
// ...
end_if_1:
cmp y, 1
beq outlined_chunk_1 // <<<<
end_if_2:
cmp ...
// ...
// rest of the function
// ...
ret
outlined_chunk_1:
// ... result of 200 lines of code
oc1_ret:
jmp end_if_2