我的代码如下:
void foo(unsigned long k)
{
if (k & 1)
{
bar(k/2 + 1);
bar(k/2);
bar(k/2 + 1);
}
else
{
bar(k/2);
bar(k/2);
bar(k/2);
}
}
void bar(unsigned long k)
{
switch(k)
{
case default: special_default(); break;
case 1: specialbar1(); break;
case 2: specialbar2(); break;
<more cases>
case 16: specialbar16(); break;
}
}
当为foo
的偶数值调用k
时,性能会好得多。每个specialbar#()
方法都使用多个堆栈变量,随着k
的增加,这些变量的数量急剧增加。要明确specialbar#()
使用约3 * k
个局部变量,所有这些变量都是unsigned long long
变量。
例如foo(32)
的执行速度比foo(31)
快约15%。我正在使用Visual Studio 2012,性能分析向我保证,对specialbar16
的两次调用和对specialbar15
的一次调用比对specialbar16
的三次连续调用要多得多。
当k
是偶数时,编译器是否可以利用连续三次调用?也就是说,它是否可以实现在偶数k
的三次连续调用中堆栈基本相同但奇数k
无法进行相同的优化?
答案 0 :(得分:2)
当k为偶数时,编译器是否可以利用三次连续调用?那就是它可以意识到堆栈在连续三次连续调用中基本相同,但奇数k不可能进行相同的优化吗?
这似乎不值得回答,但是,是的,这完全有可能。编译器可以识别每次调用需要相同的堆栈布局,因为它每次都是相同的方法,因此避免了每个方法调用的整个堆栈设置/拆除。在这种情况下,可能还会内联方法调用 - 代码在调用者中生成。
最有可能对其他情况执行类似的优化,尽管优化很棘手,并且有时会有一些细微的原因导致编译器无法执行它。
答案 1 :(得分:1)
当k为奇数(k / 2 + 1)+ 1时,你的foo函数会执行额外的逻辑。
要回答您的具体问题,可以重复通话以提高效果。是的,当参数相同时,函数中的各个部分是相同的,这样可以使“分支预测”最佳地工作。