44

是否有任何可移植的方式来进行分支预测提示?考虑以下示例:

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

这与做有什么不同:

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

或者是使用编译器特定提示的唯一方法?(例如 GCC 上的 __builtin_expect)

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

4

6 回答 6

30

进行静态分支预测的规范方法if是预测不分支(即每个if子句都被执行,而不是else),并且采用循环和后向gotoelse因此,如果您期望静态预测很重要,请不要使用常见情况。绕过未使用的循环并不容易。我从未尝试过,但我想把它放在一个else子句中应该可以很方便地工作。

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

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

正如 GNU 在文档中推荐的那样__builtin_expect,配置文件引导的优化优于提示,而且工作量更少。

于 2010-09-13T17:44:52.203 回答
21

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

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

实际上是

evaluate(A)

if (!A)
{
   jmp p1
}

... code A

   jmp p2

p1:

... code !A

p2:

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

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

结论:

  1. 如果 X 比 !X 更有可能,则执行 If(X)
  2. 尝试尽早评估 A,以便 CPU 可以动态优化流水线。

evaluate(A)

do more stuff

if (A)
   ...
于 2010-09-13T17:55:01.320 回答
7

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

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

于 2010-09-13T17:38:14.990 回答
7

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

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

于 2020-01-30T18:37:37.463 回答
1

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

于 2010-09-13T18:06:25.630 回答
1

只要与你所做的保持一致。我喜欢用

if (!(someExpression))

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

于 2010-09-13T17:37:47.837 回答