我知道现代CPU设计中有一个分支预测器,试图猜测去哪个分支。
假设有一条跳转指令将控制流转移到基本块A或基本块B。
如果预测器决定走A,当实际计算来到跳转指令时,发现B应该是正确的选择而不是A,此时,基本块A中的执行走多远?
基本块A中的所有指令都执行完成了吗?还是只执行了第一条指令?
我们如何找出实际结果并了解更多关于分支预测策略的信息?
CPU假设分支预测是正确的,并继续进行,除非/直到它发现它不是。(硬件无法检测到“基本块”:它不知道何时到达其他指令分支到的地址。无论如何你都不想停止。现代分支预测足够好,可以在无序CPU中使用,通常95%到99%的时间都是正确的。)
当分支指令本身被解码(无条件直接分支)或执行(条件和/或间接)时,就会发现错误预测(或确认正确预测)。
如果预测错误,CPU必须重新引导前端(获取/解码)到正确的路径。在有序CPU中,分支之后的任何指令都不能执行,直到分支本身执行,所以这总是一个重新启动获取/解码的问题。
(顺序超标量实际上可以在分支之后执行一条指令,但是顺序流水线使得它在到达回写和实际改变架构状态之前相对容易被挤压。存储可能是最棘手的,因为你需要丢弃存储缓冲区条目;它的可见影响将是对内存的影响,而不是对寄存器的回写。但无论如何,这以及将执行与缓存未命中存储解耦以及其他原因,就是为什么即使是顺序流水线CPU也有存储缓冲区的原因。)
或者对于推测执行的乱序CPU,允许来自错误路径的指令在条件或间接分支等待其输入时实际执行,它必须刷新后端并从正确的执行路径重新启动问题。
(使用快速恢复和分支顺序缓冲区,即使分支之前的一些指令还没有完成执行,也会发生这种情况。例如,在循环主体中具有简单循环条件和较长依赖链的循环中,因此循环条件依赖链的执行可以提前运行,并在循环分支失败时发现上一次迭代中的错误预测,而无需等到该指令准备好退出。即无需等待循环主体执行那么远。)
多个分支可以同时运行。当然,任何负载或存储都可能出错。一个OoO高管CPU基本上把一切都视为投机,直到退休。
运行中未执行分支数量的限制因素可能是分支顺序缓冲区(BOB)的大小,在这种情况下,它在ROB(重新排序缓冲区)之前填满,ROB必须跟踪每个尚未停用的指令。
我希望分支可以在执行(确认预测或检测错误预测并启动恢复)后离开BOB,而无需停用。如果之前检测到错误猜测,则该分支无论如何都在错误的路径上,因此其输入可能是错误的。如果相同的分支指令沿着新确定的正确执行路径进入管道,它将再次从前端发出并分配一个新的BOB条目。
因此,没有必要将BOB条目一直分配到退休;更早地释放它可以让它被重新分配给尚未执行的年轻分支。(潜在地,有一些旧的缓存未命中负载不是一堆后来分支的数据依赖项,让ROB充满指令,这些指令可以在负载最终到达之前完成执行,所有依赖链和猜测都尘埃落定。)
一个典型的(?)BOB大小是Skylake中的48个条目。较旧或较低端CPU的BOB可能要小得多,以配合其较小的乱序推测窗口。
在没有快速恢复(没有BOB)的CPU上,其他乱序执行资源将是分支推测深度的上限,例如重新排序缓冲区(未停用的操作)和/或调度程序(未执行的操作)。
我们如何…了解更多关于分支预测策略的信息?
https://danluu.com/branch-prediction/非常好。另请参阅Agner Fog的microarch指南(适用于x86)的第一章,其中他介绍了真正的Intel和AMDCPU的功能,以及一些背景知识。https://agner.org/optimize/
相关re:现代IT-TAGE预测(Haswell和Zen 2及更高版本):
相关re:管道的东西: