3

我的代码如下所示:

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). 我正在使用 Visual Studio 2012,性能分析向我保证,两次调用specialbar16和一次调用specialbar15比连续三次调用specialbar16.

编译器是否有可能在k偶数时利用三个连续调用?也就是说,它能否意识到堆栈在连续三个连续调用中基本相同,k但对于奇数不可能进行相同的优化k

4

2 回答 2

2

当 k 为偶数时,编译器是否有可能利用三个连续调用?也就是说,它能否意识到堆栈在连续三个连续调用偶数 k 时基本相同,而奇数 k 不可能进行相同的优化?

这似乎不值得回答,但是,是的,这完全有可能。编译器可能会认识到每次调用都需要相同的堆栈布局,因为它每次都是相同的方法,因此避免了每个方法调用的整个堆栈设置/拆卸。在这种情况下,可能还内联方法调用 - 代码在调用者中就地生成。

对于另一种情况,很可能也可以执行类似的优化,尽管优化很棘手,有时编译器无法执行它的原因很微妙。

于 2013-08-05T14:07:17.660 回答
1

当 k 为奇数 (k/2 + 1) + 1 时,您的 foo 函数会执行额外的逻辑。

要回答您的具体问题,重复调用能否提高性能。是的,当参数相同时,函数内的部分也可以相同,这允许“分支预测”以最佳方式工作。

于 2013-08-05T14:09:57.663 回答