【问题标题】:Are BOOST_LIKELY and __builtin_expect still relevant?BOOST_LIKELY 和 __builtin_expect 仍然相关吗?
【发布时间】:2015-07-27 19:19:32
【问题描述】:

我了解here 的解释以及这些将包括对 CPU 进行静态分支预测的提示。

我想知道这些在 Intel CPU 上的相关性如何,因为 Intel CPU 已经放弃了对 here 提到的静态预测提示的支持。另外,如果我现在了解它的工作原理,那么路径中的分支指令的数量将是编译器可以控制的唯一内容,并且预测、获取和解码的分支路径是在运行时决定的。

鉴于此,是否存在代码中的分支提示对于针对最新英特尔处理器的软件仍然有用的情况,可能使用条件返回或在嵌套 if/else 语句的情况下避免关键路径中的分支指令数量?

此外,如果这些仍然相关,任何有关 gcc 和其他流行编译器的细节都将受到赞赏。

附:我不是为了过早优化或在代码中添加这些宏,但我对这个主题很感兴趣,因为我正在处理一些时间关键的代码,并且仍然希望尽可能减少代码混乱。

谢谢

【问题讨论】:

  • 生成代码以使预期的路径在内存中在一起仍然可以提高代码局部性,并且编译器可以控制它。
  • @Jester 谢谢。同意它可以提高指令缓存性能。想知道当针对特定处理器时,gcc 现在是否会这样做。
  • 另外,AFAIK,方法在编译/链接期间不会被拆分。因此,对于 if/else 的小方法/控制块,局部性改进可能没有多大帮助。
  • 简而言之,blog.man7.org/2012/10/how-much-do-builtinexpect-likely-and.html 认为,如果您的预测正确 > 99.99%(示例为 1 万分之一),它们是有意义的,当然这取决于编译器、cpu 等。
  • 在阅读了更多内容并查看了上述博客中提供的代码的反汇编(在一个沙桥盒子上并使用 -O3 -march=native 编译)之后,我可以说:1.没有特别的机器代码中包含的指令/提示。预测是通过硬件分支预测器进行的。 2. 当预测器没有任何地址历史时,前向跳转被预测为未采取,后向跳转被预测为已采取。 3. 编译器为示例生成不同的代码,使代码受益于“2”中描述的行为。

标签: gcc assembly boost intel


【解决方案1】:

在你的问题的 cmets 部分中,你正确地发现:

  1. 在 Intel x86 CPU 上,操作码映射中不再有静态分支预测提示;
  2. “冷”条件跳转的动态分支预测倾向于预测失败路径;
  3. 编译器可以使用 __builtin_expect 重新排序 if-then-else 构造的路径将作为失败案例放置在生成的程序集中。

现在,考虑为多个目标架构编译的代码库,而不仅仅是 Intel x86。它们中的许多确实具有静态分支提示、不同复杂度的动态分支预测器,或两者兼而有之。

例如,英特尔安腾架构确实为所有类型的指令提供了广泛的预测提示系统:控制流、加载/存储等。安腾的设计目的是让编译器对所有这些静态分配的代码进行广泛优化捆绑和提示中的说明插槽。

因此,__builtin_expect 仍然适用于(罕见的)以下情况:1) 正确的分支预测信息太难由编译器自动推断,以及 2) 至少一个目标架构上的底层硬件也已知无法可靠地动态预测它们。鉴于某些低功耗处理器包含不跟踪分支历史但始终选择失败路径的原始分支预测器,它开始看起来很有用。对于现代 Intel x86 硬件来说,不是那么多。

【讨论】:

  • 未采用的分支仍然比采用的便宜,即使两者都正确预测:正确预测时不会出现任何前端气泡,并且它们可以在更多执行端口上运行(英特尔 Haswell)。并且将所有热门代码放在一起对于 L1I / uop-cache locality / density 更好。编译器还可能根据可能与否做出其他决定(例如,选择不膨胀代码自动矢量化一个不太可能运行的循环,也许)。或者,如果条件不太可能,可以选择使用分支而不是 cmov。
  • 如果我错了,请纠正我,但这不是“向前跳跃的跌倒而不是跌倒的预测”
猜你喜欢
  • 2010-09-19
  • 2011-06-18
  • 1970-01-01
  • 2010-09-08
  • 2014-12-04
  • 2016-03-06
  • 2016-02-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多