3

我一直在阅读有关分支预测的内容,但我发现的唯一实现主要是在计算机的硬件方面。处理器似乎处理了大部分预测。我的问题是,编译器可以进行分支预测吗?我唯一发现的是 2 种方法,函数内联和循环展开。这些被认为是正确的吗?他们还在使用吗?

4

1 回答 1

8

当然。如果编译器知道:

  • 检测运行收集的统计分支概率
  • 仪器运行收集的变量值的统计分布;然后它可以预测条件的平均结果,从而预测分支
  • 程序员关于条件的频率或偏差的断言
  • 基于范围的循环边界估计(如果未知,则默认为“10”:)
  • 知道一个分支倒退到循环的顶部(预测“采取”

使用这些信息,它可以预测条件的可能结果,然后生成倾向于由硬件正确“预测”的分支指令。

一些编译器完成的一组特别有趣的优化是跟踪调度,它根据顺序遇到的分支的概率确定通过代码的路径集。通过确定最高概率路径,编译器可以在整个路径上进行优化,而不是仅仅在基本块内进行优化。

有时编译器会生成间接使用硬件分支预测能力的分支代码。编译的 OO 语言(静态或 JITted)必须编译方法调用,并且间接跳转很昂贵。一个便宜的技巧是在每个调用站点保留一个最近调用的方法的小型动态缓存,并检查正在调度的对象类型。如果在调用站点频繁使用相同类型的对象进行调度,则缓存中第一个(并且第二个稍少)条目的比较/分支序列很有可能,因此执行的代码可以避免错误预测。这比间接跳转要好得多。

最后一个标准技巧:如果你可以避免做一个分支,你就不必正确预测它!许多代码序列看起来像这样:

  if (exp1 relop exp2)
      X = Y
  endif

现代 CPU 具有实际上是“MOV_if_relop A to B”的“谓词”指令,适用于所有关系条件相等、不相等、小于等。因此,编译器不会为上述构造生成分支,而是生成:

  <compute exp1 and exp2>
  CMP  exp1,exp2 ; sets condition code
  MOVif_relop  X,Y
于 2012-05-12T08:31:18.033 回答