让我们说说预测的算法吧。
对于无条件跳转,没啥可犹豫的,直接跳过去就是了。所谓的预测是针对有条件跳转来说的,因为不知道条件成不成立。最简单的统计是根据上一次跳转的结果来预测本次,如果上一次跳转啦,这一次也预测为跳转,否则不跳。
最简单的方法是2位预测法。用2位bit的计数器来记录跳转状态,每跳转一次就加1,直到加到最大值3就不再加啦,如果未跳转就减1,直到减到最小值0就不再减了。当遇到跳转指令时,如果计数器的值大于1则跳转,如果小于等于1则不跳。这只是最简单的分支预测算法,cpu中的预测法远比这个复杂,不过它们都是从2位预测法发展起来的。
算法有了,咱们看看cpu是如何实现预测的。
intel的分支预测部件中用了BTB,Branch Target Buffer,分支目标缓冲器。其结构见图
BTB中记录着分支指令地址,cpu遇到分支指令时,先用分支指令的地址在BTB中查找,若找到相同地址的指令,根据跳转统计信息判断是否把相应的预测分支地址上的指令送上流水线。在真正执行时,根据实际分支流向,更新BTB中跳转统计信息。
如果BTB中没有相同记录该怎么办呢?这时候可以使用Static Predictor,静态预测器。为什么称为静态呢?这是因为存储在里面预测策略是固定写死的,它是经由人们经过大量统计之后,根据某些特征总结出来的。比如,转移目标的地址若小于当前转移指令的地址,则认为转移会发生,因为通常循环结构中都用这种转移策略,为的是组成循环回路。所以静态预测器的策略是:若向上跳转则转移会发生,若向下跳转则转移不发生,如图
程序在实际执行转移分支指令后,再将转移记录录入到BTB。
还记得之前反复强调的重叠吗?其实是用在这的。如果分支预测错了,也就是说,当前指令执行结果与预测的结果不同,这也没关系,只要将流水线清空就好了。因为处于执行阶段的是当前指令,即分支跳转指令。处于“译码”、“取指”的是尚未执行的指令,即错误分支上的指令。只要错误分支上的指令还没到执行阶段就可以挽回,所以,直接清空流水线就是把流水线上错误分支上的指令清掉,再把正确分支上的指令加入到流水线,只是清空流水线代价比较大。
好啦各位,关于微架构这块咱们说到这就够用了,咱们当初是想解决代码4-3中第78行的清空流水线的,不能偏离目标太远啦。