分支预测:不用等到分支指令的结果真的被计算出来,而是提前就预测结果的过程。
分支预测之所以能够实现,是由分支指令的特性决定的,因为分支预测本质上是对分支指令的结果进行预测,而在一般的RISC指令集中,分支指令包含两个要素:
- 方向,taken or not taken;
- target pc, 跳转的目标地址,该目标地址携带在指令中;有两种存在形式:
- 直接跳转,PC relative, target pc = current pc + offset;
- 间接跳转,indirect, 其目标地址来自于一个通用寄存器的值,该寄存器的编号从指令给出;
- 间接跳转使用的通用寄存器,可能依赖于其他指令,所以可能需要等待一段时间才能得到目标地址;
- 这就会导致如果预测失败,带来的misprediction penalty很大;
- 还有一方面,这种寄存器的值,是随时变化的,所以很难预测,只有call/return这类规律性很强的指令,才推荐这种方式;
预测方式分为两种:静态分支预测和动态分支预测;
- 静态分支预测:总是预测跳转或者不跳转;
- 动态分支预测:根据分支指令在过去一段时间的情况来决定预测结果;
Fetch出来的指令,怎么知道是分支指令?
- fast decode的方式;?
- 将指令组中的指令从1-Cache取出来之后,进行快速的解码,之所以称为快速,是因为只需要辨别解码指令是否是分支指令,然后将找到的分支指令对应的PC值送到分支预测器(branch predictor)中,就可以对分支指令进行预测;
- 缺点:
- fast decode和prediction放在同一个cycle, 频率很差;
- 如果频率提高,则需要将这些电路放在多个cycle, 则在这段时间内,只能顺序取指令(即认为分支指令不跳转),降低了处理器性能;
- 预解码;
- 在指令从 L2 Cache 写入到 I-Cache之前进行快速解码;
- 将指令是否是分支指令的信息和指令一起写到 I-Cache中;
- 解决不了如下问题:
- 指令取出来,到分支预测成功,这段时间是多个周期,仍然解决不了在这个时间范围内进行顺序取址的问题;
- 使用PC值
- 流水线中,分支预测越靠前越好,如果取址之后才预测,则到预测出结果,需要多个cycle, 这个misprediction penalty太大了;
- 对于一条指令来说,它的物理地址是会变化的(这取决于操作系统将它放到物理内存的位置),而它的虚拟地址,也就是PC值,是不会变化的;
- 只要这条分支指令第一次被执行完之后,当后面再次遇到这个PC值,就可以知道当前要取的指令是分支指令;
- 即使发生了自修改(self-modifying)的情况,也会将分支预测器清空,重新开始进行分支预测,并不会影响分支预测的过程;
- 所以可以使用PC值,来进行分支预测;
- 对于多个进程,则可以使用asid+pc的方式进行预测,如果没有asid, 则切换进程时,需要对分支预测器中的内容进行清空操作,保证不同进程之间不会互相影响;