便携式分支预测提示

Osk*_* N. 38 c c++ compiler-construction optimization branch-prediction

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

  if (unlikely_condition) {
    /* ..A.. */
  } else {
    /* ..B.. */
  }
Run Code Online (Sandbox Code Playgroud)

这有什么不同于:

  if (!unlikely_condition) {
    /* ..B.. */
  } else {
    /* ..A.. */
  }
Run Code Online (Sandbox Code Playgroud)

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

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

Pot*_*ter 27

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

许多编译器支持某种形式#pragma unroll,但仍然需要保护它#if以保护其他编译器.

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

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


Lio*_*gan 19

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

if (a)
{
   ...
}
else
{
    ...
}
Run Code Online (Sandbox Code Playgroud)

实际上是

evaluate(A)

if (!A)
{
   jmp p1
}

... code A

   jmp p2

p1:

... code !A

p2:
Run Code Online (Sandbox Code Playgroud)

请注意,如果A为真,则"代码A"已经在管道中.处理器将提前看到"jmp p2"命令,并将p2代码加载到管道.

如果A为假,则"代码!A"可能不在pipleline中,因此它可能更慢.

结论:

  1. 如果(X),如果X比X更可能
  2. 尽可能早地评估A,以便CPU可以动态优化管道.

:

evaluate(A)

do more stuff

if (A)
   ...
Run Code Online (Sandbox Code Playgroud)


GMa*_*ckG 8

优化本质上是编译器的事情,因此您必须使用编译器功能来帮助它.语言本身并不关心(或授权)优化.

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

  • 尽管如此(`inline`,`restrict`,`register`)提供优化提示的语言还有很多先例.有些在现代编译器上比其他人更有意义.一个特定的实现是否实际上对它们做了什么并不重要:如果有一些合理的机会做一些有用的东西,那么它将是一个很好的功能.我认为主要的静态分支预测不符合这个标准,所以我认为将其排除在外是不好的.这是对案件案情的判断,但并不完全"我们不关心优化,永远". (5认同)
  • 我认为`restrict`可能是值得过早的优化.它不会造成任何伤害,它可能会通过防止可怕的存储/负载依赖性来实现显着的好处,并且它应用的地方可能是文档化的需求(如`memcpy`),无论是否反映在源中.其他人(以及在C++ 03中),我同意你的响亮"meh":-) (2认同)

Ton*_*ous 7

C++20 提供了可能和不可能的属性

允许编译器针对包含该语句的执行路径比不包含此类语句的任何替代执行路径更可能或更不可能的情况进行优化