什么是乱序执行
乱序执行 [1] ,简单说就是程序里面的代码的执行顺序,有可能会被编译器、CPU 根据某种策略调整顺序(俗称,“打乱”)——虽然从单线程的角度看,乱序执行不影响执行结果。
为什么需要乱序执行
主要原因是 CPU 内部采用 流水线技术 [2] 。抽象且简化地看,一个 CPU 指令的执行过程可以分成 4 个阶段:取指、译码、执行、写回。
这 4 个阶段分别由 4 个独立物理执行单元来完成。这种情况下,如果指令之间没有依赖关系,后一条指令并不需要等到前一条指令完全执行完成再开始执行。而是前一条指令完成取指之后,后一条指令便可以开始执行取指操作。
比较理想的情况如下图所示:指令之间无依赖,可以使流水线的并行度最大化。
在 按序执行 的情况下,一旦遇到指令依赖的情况,流水线就会停滞。比如:
指令 1: Load R3 <- R1(0) # 从内存中加载数据到 R3 寄存器
指令 2: Add R3 <- R3, R1 # 加法,依赖指令 1 的执行结果
指令 3: Sub R1 <- R6, R7 # 减法
指令 4: Add R4 <- R6, R8 # 加法
上面的伪代码中,指令 2 依赖指令 1 的执行结果。该指令 1 执行完成之前,指令 2 无法执行,这会让流水线的执行效率大大降低。
观察到,指令 3 和指令 4 对其它指令没有依赖,可以考虑将这两条指令”乱序“到指令 2 之前。
这样,流水线执行单元就可以尽可能处于工作状态。
总的来说,通过乱序执行,合理调整指令的执行顺序,可以提高流水线的运行效率,让指令的执行能够尽可能地并行起来。
Compiler Fence
在多线程的环境下,乱序执行的