英特尔架构的开发人员手册(Vol3A,第 8-26 节)说:
Pentium 处理器和更新的处理器系列使用分支预测技术通过在执行分支指令之前预取分支指令的目标来提高性能。因此,当执行分支指令时,指令执行不是确定性地串行化的。
这是什么意思?
听起来真的,真的很糟糕。听起来像 CPUID 这样的序列化指令会破坏分支预测(反之亦然),但这似乎不太可能。任何 ASM 人员都可以帮助我理解“非确定性”在这种情况下的含义。
*为清晰起见进行了编辑
英特尔架构的开发人员手册(Vol3A,第 8-26 节)说:
Pentium 处理器和更新的处理器系列使用分支预测技术通过在执行分支指令之前预取分支指令的目标来提高性能。因此,当执行分支指令时,指令执行不是确定性地串行化的。
这是什么意思?
听起来真的,真的很糟糕。听起来像 CPUID 这样的序列化指令会破坏分支预测(反之亦然),但这似乎不太可能。任何 ASM 人员都可以帮助我理解“非确定性”在这种情况下的含义。
*为清晰起见进行了编辑
它的措辞非常混乱,但我相信它的实际含义很简单:“分支不会(必然)序列化执行”。我们今天认为这是理所当然的,但并非总是如此。
我怀疑你误解了那句话,但我不知道具体是怎么回事。您认为序列化指令和分支预测之间有什么联系?当它说“指令执行不是确定性地序列化”时,它的意思是指令的预取和解码将基于分支预测逻辑来确定,因此它不会每次都以相同的方式工作。但这整件事的重点是让事情变得更快——如果分支预测很好,大多数时候正确的下一条指令将被获取、解码并准备就绪。
错误预测的分支是序列化指令,正确预测的分支不是。
因为在执行之前您不知道分支是否被正确预测,因此您无法事先知道它是否会序列化指令流。该行为是不确定的,因为它取决于分支预测。
您可能会在条件分支之前和之后构造一个带有内存访问的极端情况,其中代码的行为取决于分支是否被正确预测。(即分支是否正在序列化。)
现代超标量处理器通常使指令执行看起来是完全确定的,从 CPU 外部的角度来看是有序的。在内部,它提前获取指令,推测性地执行指令,并以最有效的顺序执行它们。但是任何不应该执行的东西(例如错误预测的分支)都不会被提交,并且内存访问通常会在离开 CPU 之前恢复到正确的顺序。CPU 流水线的末端称为“重新排序缓冲区”,因为它的工作是跟踪完成的指令,并且仅按程序顺序永久提交它们的结果。这对于正确的程序行为很重要,尤其是面对分支错误预测和异常等情况时;如果发生异常(例如
With regard to memory ordering, there are some exceptions to the illusion of program ordering, where reads can get reordered arbitrarily, and there can be some (possibly speculative) reordering between reads and writes, but you only care about that when talking to memory-mapped I/O hardware. There are instructions that ensure a particular ordering, and CPUs are very careful with the ordering of accesses to un-cached memory, because that's assumed to mean it's I/O.