便携式分支预测提示

时间:2010-09-13 17:35:32

标签: c++ c optimization compiler-construction branch-prediction

有没有可行的分支预测提示方法?请考虑以下示例:

  if (unlikely_condition) {
    /* ..A.. */
  } else {
    /* ..B.. */
  }

这与做的有什么不同:

  if (!unlikely_condition) {
    /* ..B.. */
  } else {
    /* ..A.. */
  }

或者是使用编译器特定提示的唯一方法? (例如海湾合作委员会的__builtin_expect)

编译器是否会根据条件的顺序对if条件进行不同的处理?

6 个答案:

答案 0 :(得分:26)

进行静态分支预测的规范方法是预测if不分支(即执行每个if子句,而不是else),循环和后退 - {{ 1}}被采取。因此,如果您希望静态预测具有重要意义,请不要将常见情况放在goto中。绕过一个未被捕获的循环并不容易;我从来没有尝试过,但我想把它放在一个else条款应该可以很方便地工作。

许多编译器支持某种形式的else,但仍需要使用某种#pragma unroll来保护它以保护其他编译器。

分支预测提示理论上可以表达如何转换程序的流控制图并在可执行存储器中排列基本块的完整描述......所以有很多要表达的东西,而且大多数都不会非常便携。

正如GNU在#if的文档中所建议的那样,配置文件引导的优化优于提示,而且工作量更少。

答案 1 :(得分:17)

在大多数情况下,以下代码

if (a)
{
   ...
}
else
{
    ...
}

实际上是

evaluate(A)

if (!A)
{
   jmp p1
}

... code A

   jmp p2

p1:

... code !A

p2:

请注意,如果A为true,则“代码A”已在管道中。处理器将提前看到“jmp p2”命令,并将p2代码加载到管道。

如果A为假,则“代码!A”可能不在pipleline中,因此可能会更慢。

结论:

  1. 如果(X),如果X更可能是!X
  2. 尝试尽早评估A,以便CPU可以动态优化管道。
  3. evaluate(A)
    
    do more stuff
    
    if (A)
       ...
    

答案 2 :(得分:7)

优化本质上是一个编译器,所以你必须使用编译器功能来帮助它。语言本身并不关心(或授权)优化。

所以你可以做的最好的事情没有特定于编译器的扩展就是组织你的代码,使你的编译器在没有帮助的情况下“做正确的事情”。但是如果你想确定,请点击编译器扩展。 (您可以尝试在预处理器后面抽象它们,这样您的代码仍然可移植。)

答案 3 :(得分:5)

C ++ 20提供likely and unlikely attributes

允许编译器针对执行路径进行优化 包含该陈述的可能性比其他任何可能性都大 不包含此类声明的执行路径

答案 4 :(得分:1)

与你的工作保持一致。我喜欢用

if (!(someExpression))

但是编译器应该平等对待它。

答案 5 :(得分:1)

通过#ifdef检查特定编译器并将这些内容隐藏在自定义宏后面有什么问题?如果没有支持这些优化提示的编译器,您可以#define扩展为简单表达式。我最近做了一些与GCC通过内部函数支持的显式缓存预取类似的东西。