分支预测概述

文章探讨了在超标量处理器中,准确的分支预测对于优化性能的重要性,介绍了分支指令的要素、静态预测与动态预测的区别,以及如何通过预解码和利用PC值进行早期预测以减少流水线错误。分支预测的复杂性与处理器设计中的权衡是本文的核心内容。
摘要由CSDN通过智能技术生成

对于超标量处理器来说,准确度高的分支预测更为重要;

  • 在取指令阶段,除了需要从1-Cache中取出多条指令,同时还需要决定下个周期取指令的地址;
  • 如果只是顺序取指,有可能中间有跳转指令,导致取回来的指令,实际上是没有用的;
  • 也就是说,预测所有的分支指令都是不执行的,那么等到在流水线的后续阶段,例如执行阶段,发现了一条可以执行的分支指令时,就需要将流水线中,执行阶段之前的全部指令都从流水线中清除(flush),并重新从正确的地址开始取指令。这些从流水线中被抹掉的指令都做了无用功,浪费了处理器的功耗,并且降低了执行效率。

因此,引入分支预测的概念:这样,不用等到执行阶段的分支指令结果被计算出来,而是在取指之后,就提前预测了分支指令的结果;

分支指令的两个要素

  1. 方向

        taken, or not taken;

  1. 目标地址

      目标地址携带在指令当中;有两种存在形式;        

  • PC relative,也称做直接跳转(direct)。
    • 在指令中直接以立即数的形式给出一个相对于 PC 的偏移值(offset),当前分支指令的PC值(或者分支指令的下一条指令的 PC 值加上这个偏移值就可以得到分支指令的目标地址。
    • 有一个特点:由于指令的长度只有32位,它限制了立即数的大小范围,因此这种类型的分支指令,它的跳转范围一般不大,但是由于需要的信息直接携带在指令中,这样就很容易计算它的目标地址。
  •  Absolute,也称做间接跳转(indirect)。
    • 分支指令的目标地址来自于一个通用寄存器的值,这个寄存器的编号由指令给出,这就是说,它的目标地址是32 位的值,因此可以跳转到处理器程序空间中的任意地方。
    • 但是,这个通用寄存器的值一般来自于其他指令的结果,因此对于分支指令来说,可能需要等待一段时间才可以得到这个目标地址;
    • 在这段时间内进入到流水线中的指令都是有可能不正确的,这就增大了分支预测失败时的惩罚(misprediction penalty)。
    • 而且,由于寄存器的值是会经常变化的,因此这种类型的分支指令很难对目标地址进行预测,
    • 但是庆幸的是,程序当中大部分间接跳转的分支指令都是用来调用子程序的CALL/Return类型的指令,而这种类型的指令由于有着很强的规律性,是容易被预测的。
    • 除了CALL/Return 指令之外,一般的处理器都不会推荐使用间接跳转类型的分支指令。
  • 通常采用静态分支预测,即总是预测taken, or not taken;
  • MIPS处理器为了减少这一个周期的浪费,在分支指令之后会放置一条不相关的指令;
  • 这条指令总是会被执行,而不管分支指令是否发生跳转,分支指令之后的那个位置就被MIPS称为分支延迟槽(branch delay slot);
  • 需要编译器(compiler)或者程序员从分支指令之前的程序中找到不相关的指令放到延迟槽的位置。
  • 随着流水级数的加深,显然这种处理方式的准确率太低了;

动态分支预测

动态分支预测并不会简单地预测分支指令一直发生跳转或者不跳转,而是会根据分支指令在过去一段时间的执行情况来决定预测的结果,这也是为什么将它称为“动态”的原因;

  • 分支预测的难点一:怎么知道哪条指令是分支指令?

 要进行分支预测,首先需要知道从I-Cache取出来的指令中,哪条指令是分支指令,这对于每周期取出多条指令的超标量处理器来说,更为不容易,需要从指令组(fetch group)中找出分支指令;

  •  方式一:快速解码

  • 将指令组中的指令从1-Cache取出来之后,进行快速的解码,之所以称为快速,是因为只需要辨别解码指令是否是分支指令,然后将找到的分支指令对应的PC 值送到分支预测器(branch predictor)中,就可以对分支指令进行预测了;
  • 存在的问题:
  1. 当处理器的周期时间比较小时,I-Cache的访问可能需要多个周期才可以完成;
  2.  采用图 4.3 所示的方式进行分支预测,从开始取指令直到分支预测得到结果,中间需要间隔好几个周期,在这些周期内无法得到准确的预测结果,只能够顺序地取指令;
  3. 也就相当于这些周期都是预测分支指令不发生跳转,这样就降低了分支预测的准确度,造成了处理器性能的降低;
  4. 指令快速解码(fast decode)和分支预测的过程都放在了同一个周期,严重影响了处理器的周期时间。
  • 方式二:预解码; 
    • 可以解决上面fast decode与分支预测同周期的问题;
    • 在指令从 L2 Cache 写入到 I-Cache之前进行快速解码,这也被称为预解码(pre-decode);
    • 然后将指令是否是分支指令的信息和指令一起写到 I-Cache中,这样虽然会使I-Cache 占用更多的面积,但是可以省掉图 4.3 中的快速解码电路,在一定程度上缓解对处理器周期时间的影响;
    • 但是,取指令直到分支预测得到结果这两个阶段的间隔时间仍然是过长的,无法得到解决。
  •  方式三:根据pc值进行分支预测;
    • 在流水线中,分支预测是越靠前越好的;
    • 如果指令从I-Cache取出来之后才进行分支预测,如图 4. 3 所示,那么由于I-Cache中取出指令的过程可能需要多于一个周期才能够完成;
    •  当得到分支预测结果时,已经有很多后续的指令进入了流水线,当得到的预测值是要发生跳转时,这些指令都需要从流水线中被抹掉(flush),这样就降低了处理器的执行效率。 
    • 解决方式:
      • 因此分支预测的最好时机就是在当前周期得到取指令地址的时候;
      • 在取指令的同时进行分支预测,这样在下个周期就可以根据预测的结果继续取指令。
      • 对于一条指令来说,它的物理地址是会变化的(这取决于操作系统将它放到物理内存的位置),而它的虚拟地址,也就是PC值,是不会变化的。
        • 因为在一个进程内,每一个PC值对应的指令是固定的,不可能出现一个 PC值对应多条指令的情况,所以使用 PC值进行分支预测;
        • 只不过在进行进程切换之后,需要将分支预测器中的内容进行清空,这样可以保证不同进程之间的分支预测不会互相干扰。
        • 如果使用了 ASID,那么可以将它和 PC值一起进行分支预测,此时就不需要在进程切换时清空分支预测器了

 分支预测本身是比较复杂的,不同的处理器有不同的实现方法,它是影响一款处理器性能高低的关键因素之一,需要在处理器设计的时候仔细进行权衡和折中,以便在硬件消耗、预测准确度和延迟(latency)之间找到一个平衡点。

  • 17
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值