The Core Execution Engine: Out-of-Order Execution
处理器核心执行引擎:乱序执行
OOOE——Out-of-Order Execution乱序执行也是在Pentium Pro开始引入的,它有些类似于多线程的概念,这些在《机密揭露:Intel超线程技术有多少种?》里面可以看到相关的介绍。乱序执行是为了直接提升ILP(Instruction Level Parallelism)指令级并行化的设计,在多个执行单元的超标量设计当中,一系列的执行单元可以同时运行一些没有数据关联性的若干指令,只有需要等待其他指令运算结果的数据会按照顺序执行,从而总体提升了运行效率。乱序执行引擎是一个很重要的部分,需要进行复杂的调度管理。
然而乱序执行架构中,不同的指令可能都会需要用到相同的通用寄存器(GPR,General Purpose Registers),为了在这种情冲突的况下指令们也能并行工作,处理器需要准备解决方法。一般的RISC架构准备了大量的GPR,而x86架构天生就缺乏GPR(x86具有8个GPR,x86-64具有16个,一般RISC具有32个,IA64则具有128个),为此Intel开始引入重命名寄存器(Rename Register),不同的指令可以通过具有名字相同但实际不同的寄存器来解决,这有点像魔兽世界当中的副本设计,当然其出现要比WoW早多了。
此外,为了SMT同步多线程,这些寄存器还要准备双份,每个线程具有独立的一份。
The Core Execution Engine: Out-of-Order Execution
乱序执行从Allocator定位器开始,Allocator管理着RAT(Register Alias Table,寄存器别名表)、ROB(Re-Order Buffer,重排序缓冲区)和RRF(Retirement Register File,退回寄存器文件)。在Allocator之前,流水线都是顺序执行的,在Allocator之后,就可以进入乱序执行阶段了。在每一个线程方面,Nehalem和Core 2架构相似,RAT将重命名的、虚拟的寄存器(称为Architectural Register或Logical Register)指向ROB或者RRF。RAT是一式两份,每个线程独立,每个RAT包含了128个重命名寄存器(Pentium 4之前——Pentium Pro到Pentium III的重命名寄存器基于ROB,数量为40个;据说Pentium 4有128个)。RAT指向在ROB里面的最近的执行寄存器状态,或者指向RRF保存的最终的提交状态。
ROB(Re-Order Buffer,重排序缓冲区)是一个非常重要的部件,它是将乱序执行完毕的指令们按照程序编程的原始顺序重新排序的一个队列,打乱了次序的指令们依次插入这个队列,当一条指令通过RAT发往下一个阶段确实执行的时候这条指令(包括寄存器状态在内)将被加入ROB队列的一端,执行完毕的指令(包括寄存器状态)将从ROB队列的另一端移除(期间这些指令的数据可以被一些中间计算结果刷新),因为调度器是In-Order顺序的,这个队列也就是顺序的。从ROB中移出一条指令就意味着指令执行完毕了,这个阶段叫做Retire回退,相应地ROB往往也叫做Retirement Unit(回退单元),并将其画为流水线的最后一部分。
在一些超标量设计中,Retire阶段会将ROB的数据写入L1D缓存,而在另一些设计里,写入L1D缓存由另外的队列完成。例如,Core/Nehalem的这个操作就由MOB(Memory Order Buffer,内存重排序缓冲区)来完成。
ReOrder Buffer重排序缓冲区是一个Retire Queue回退队列,是OOOE乱序架构流水线的最后一段
ROB是乱序执行引擎架构中都存在的一个缓冲区,重新排序指令的目的是将指令们的寄存器状态依次提交到RRF退回寄存器文件当中,以确保具有因果关系的指令们在乱序执行中可以得到正确的数据。从执行单元返回的数据会将先前由调度器加入ROB的指令刷新数据部分并标志为结束(Finished),再经过其他检查通过后才能标志为完毕(Complete),一旦标志为完毕,它就可以提交数据并删除重命名项目并退出ROB了。提交状态的工作由Retirement Unit(回退单元)完成,它将确实完毕的指令包含的数据写入RRF(“确实”的意思是,非猜测执性、具备正确因果关系,程序可以见到的最终的寄存器状态)。和RAT一样,RRF也同时具有两个,每个线程独立。Core/Nehalem的Retirement Unit回退单元每时钟周期可以执行4个uops的寄存器文件写入,和RAT每时钟4个uops的重命名一致。