分支预测用于在微处理器中以流水线效率为目标来预测程序流。有许多方法来实现分支预测,通常在更好的预测结果和增加硬件做预测之间需要进行权衡。
目录
分支预测简介
静态分支预测
动态分支预测
启动分支预测
分支预测简介
要了解分支预测器,就不得不提指令流水线。以4级流水线为例,四个步骤分别是取指、解码、执行、写回。如下图所示。
假设一条指令从执行开始到执行结束需要4个时钟周期,在没有流水线的情况下,需要等待第一条指令执行结束,才能取第二条指令,这时两条指令就用了8个周期,效率是很低的。
引入4级流水线将指令拆成4个步骤:取指、解码、执行、写回。当第一条指令处于解码时,同时对第二条指令取指;对第一条指令执行时,同时对第二条指令解码,对第三条指令取指;对第一条指令写回时,同时对第二条执行,第三条解码,第四条取指;如此这般。最终达到的效果就如上图所示,只有第一条指令需要4个周期,其他后续的指令都只需要1个周期,极大地提高了处理效率。
流水线的高效率的前提是指令顺序执行,在执行跳转指令时,流水线将被清空,又回到了上图中的第一步,跳转后的第一条指令要执行仍然需要4周期。因此如果程序频繁跳转,流水线的作用就大打折扣。
为了解决这个问题,就引入了分支预测器:它会提前检测到跳转指令,并根据预判结果取指。如果预判结果是不跳转,就按顺序取下一条指令;如果预判结果是跳转,就从跳转的目的地址取下一条指令。假如预测对了,那么流水线就不会被清空,仍然可以一条指令1个周期;如果预测错了,下一条指令仍然要4周期。从这里看出,分支预测器对于提高流水线效率是有帮助的。当然,以上情况并不适用于所有的内核,预判对错所需要的指令周期还是取决于MCU是如何设计的。
静态分支预测
其实,静态分支预测就是不预测哈哈。常用静态分支预测一般有如下几种:
- 总是不跳转:实现简单,无需跳转预测;对于条件分支来说,准确率大概为30%~40%。
- 总是跳转:实现简单,无需跳转预测;对于条件分支来说,准确率大概为60%~70%。
- BTFN(Backward taken, forward not taken):如果目标地址比当前分支指令PC小,即往前跳,则跳转(如循环);如果目标地址比当前分支指令PC大,即往后跳,则不跳。
- Profile based(likely direction):编译器使用profile运行方式确定可能的分支方向,并编码到指令中。
- Program based (likely direction):根据ISA指令特定,对不同指令采用不同的预测方向。
- Programmer based:程序员提供静态预测,通过编译器指令指示方向。if (likely(x)) {....} 指示较大概率是跳转,if (unlikyly(error)) {....} 指示较大概率是不跳转。
动态分支预测
动态预测则指在程序运行时进行预测。不同的软件、不同的程序分支行为,我们可以采取不同的算法去提高预测的准确率,如我们可以根据程序的历史执行路径信息来预测本次跳转的行为,常见的动态预测方式有1-bit动态预测、n-bit动态预测、下一行预测、双模态预测、局部分支预测、全局分支预测、融合分支预测、循环预测等。随着大量新的应用软件的出现,为了应对新的程序逻辑行为,分支预测器也做得越来越复杂,占用的芯片面积也越来越大。在CPU内部,除了Cache,就数分支预测器的电路版图最大。
举例来说:
- Last time prediction(单bit计数器):以上一次的跳转情况作为这一次是否跳转的预测,针对每个分支使用一个bit来记录上一次执行的方向,保存在BTB中,并使用分支指令PC进行索引。
- 2bit饱和计数器预测:针对每个分支指令维护一个使用2bit的饱和计数器来对历史状态进行标记,遇到一次跳转则计数器加1,遇到一次不跳转则计数器减一;预测时根据计数器的值来进行预测,预测的映射方法有多种:使用计数器的最高位来预测,即最高位为1则预测跳转,否则预测不跳转;使用计数器的值来预测,计数器非0则预测跳转,否则预测不跳转。相应的预测器结构同前述的单bit预测器类似,差别在于BTB中维护的计数器位宽以及预测的映射方式。
分支预测技术是提高CPU性能的一项关键技术,其本质就是去除指令之间的相关性,让程序更高效运行。一个CPU性能高不高,不仅在于你的流水线有多深、主频有多高、Cache有多大,还和分支预测技术息息相关。一个分支预测器好不好,我们可以从两个方面来衡量:分支判断速度和预测准确率。目前分支预测技术可以达到95%的预测准确率,然而技术进化之路永未停止,分支预测技术一直在随着计算机的发展不断更新迭代。
启动分支预测
对于Cortex-R4、Cortex-R5、Cortex-M7等支预测功能在复位时是自动启用的。不需要软件配置做就能获得最大的性能。如下图所示,内核手册中BP默认使能。
对于Cortex-R7、Cortex-R8等复位时默认不使能分支预测,这意味着软件必须使能分支预测,以获得最大的硬件性能。通过设置Z比特来使能分支预测。Z比特位于系统控制寄存器SCTLR的第11位。