3

假设我有一些函数IsTrue()返回一个bool. 如果程序员决定IsTrue()通常会返回true,她可能会使用 GCC__builtin_expect或类似的东西来加速那些典型情况下的指令。

举以下2个例子:

// example 1
const bool result = IsTrue();
if (__builtin_expect(result, true))
  // do something
  ;

// example 2
if (__builtin_expect(IsTrue(), true))
  // do something
  ;

假设这IsTrue是不平凡的,这些之间有什么区别吗?放在参数列表中是否IsTrue()会导致在知道结果之前__builtin_expect评估指令缓存,还是仅在计算结果之后才应用分支预测?IsTrueIsTrue

4

2 回答 2

3

所有现代处理器都采用超标量管道,在实际执行的指令之后预先计算指令。通过使用__builtin_expect,编译器重新排序指令,以便预期(可能)路径不会使用导致超标量管道丢失的跳转,从而使所有预先计算的结果无用。

编辑:这当然是简化的。现代处理器也具有分支预测功能,因此它们会尝试预测代码将遵循的路径,但仍然首选没有跳转的路径(缓存也更好,因为执行的代码路径很紧凑)。另请注意,这些速度变化通常是非常微小的,如果您的代码不是非常频繁地执行或确实需要尽可能高的速度,您无需担心。

于 2015-02-09T01:25:58.570 回答
1

正如 GCC 文档所说,-fprofile-generate-fprofile-use使用__builtin_expect.

CPU 内置的分支预测会缓存程序“典型”执行路径中的大部分分支。静态分支预测主要是在它为所有分支提供强数据时发挥作用,因此当编译器可以选择先执行几个测试之一时,它可以安排最有效的序列。这不仅考虑了值解析为什么,还考虑了else if最常选择的语句。

__builtin_expect很少会有所作为。对于分支程序,-fprofile-use通常会在不进行任何编程工作的情况下立即提供 10-30% 的提升。

放在参数列表中是否IsTrue()__builtin_expect导致在结果已知之前评估指令缓存IsTrue,或者分支预测仅在IsTrue计算结果后应用?

__builtin_expect发生在编译时。指令缓存甚至还不存在。编译器会猜测IsTruetrue,然后在运行时,CPU 会做出另一个更明智的猜测。

于 2015-02-09T02:33:22.840 回答