分支"期待"在现代CPU中

时间:2015-06-30 16:01:51

标签: c optimization hardware cpu-architecture branch-prediction

我最近在考虑现代CPU中的分支预测。 据我所知,分支预测是必要的,因为在管道中执行指令时,我们在获取分支之前不知道条件操作的结果。

因为我知道现代无序CPU可以按任何顺序执行指令,只要它们之间的数据依赖性得到满足,我的问题是,CPU能否以分支目标已经存在的方式重新排序指令在CPU需要占用分支时已知,因此可以预测"分支方向,所以它根本不需要猜测?

CPU也可以这样做:

do_some_work();
if(condition()) //evaluating here requires the cpu to guess the direction or stall
   do_this();
else
   do_that();

对此:

bool result = condition();
do_some_work(); //bunch of instructions that take longer than the pipeline length
if(result) //value of result is known, thus decision is always 100% correct
   do_this();
else
   do_that();

一个特殊且非常常见的用例是迭代集合,其中退出条件通常是循环不变的(因为我们通常不会在迭代时修改集合)。

我的问题是现代通常CPU可以做到这一点,如果是这样,已知哪些特定CPU内核具有此功能?

2 个答案:

答案 0 :(得分:3)

请记住,分支预测是在管道的早期完成的,您仍然没有解码指令,并且您无法解析数据依赖性,因为您不知道使用了哪个寄存器。您可能能够记住某个地方,但这不是100%(因为您的存储容量/时间将受到限制),所以这几乎是您的正常分支预测器所做的 - 仅根据指令指针推测目标。

然而,之前提取条件评估是有用的,它在过去已经完成,并且主要是编译器技术,但可以通过一些硬件支持来增强(例如 - hoisting branch condition)。分支机构错误预测的主要性能影响是评估延迟,因为现在分支机构恢复本身很短。

这意味着您可以通过编译器仅提升条件并稍早计算,并且不进行任何硬件修改来减轻大部分惩罚 - 如果您错误预测了分支(并且现代预测器的几率通常很低,但是你会在解码分支本身后立即知道(因为数据会提前准备好),所以损坏将仅限于很少的指令使它成为管道过了那个分支。

能够提升评估并不简单。在大多数情况下,编译器可能能够检测是否存在任何直接数据依赖性(在您的示例中为do_some_work()),但在大多数情况下会存在。循环不变量是编译器今天已经移动的第一件事。另外,一些最难以预测的分支依赖于一些内存提取,你通常不能假设内存保持不变(你可以,之后进行一些特殊的检查,但是大多数常见的编译器不会这样做)。无论哪种方式,它仍然是一种编译器技术,而不是分支预测的根本变化。

答案 1 :(得分:0)

完成分支​​预测是因为CPU的指令获取器需要知道在分支指令之后要获取哪些指令,直到分支执行之后才知道这一点。

如果处理器有一个5级流水线(大多数处理器有更多),就像这样:

  1. 取指令
  2. 指令解码
  3. 注册阅读
  4. ALU执行
  5. 注册回写
  6. 取出器将停止3个周期,因为在ALU执行周期之后才能知道分支结果。

    提升分支测试条件并不能解决从分支指令到执行的延迟问题。