为什么在单个 CPU 内核上不会出现指令重新排序问题?

Why doesn't the instruction reorder issue occur on a single CPU core?

从这个post:

Two threads being timesliced on a single CPU core won't run into a reordering problem. A single core always knows about its own reordering and will properly resolve all its own memory accesses. Multiple cores however operate independently in this regard and thus won't really know about each other's reordering.

为什么单个 CPU 内核不能发生指令重新排序问题?本文不做解释。

示例:
以下图片摘自Memory Reordering Caught in the Act:

记录如下:

我认为记录的说明也会导致单个 CPU 出现问题,因为 r1r2 都不是 1

A single core always knows about its own reordering and will properly resolve all its own memory accesses.

单个 CPU 核心 重新排序,但它知道这是自己的重新排序,并且可以巧妙地假装它不是。因此,事情进展得更快,没有奇怪的副作用。

Multiple cores however operate independently in this regard and thus won't really know about each other's reordering.

当 CPU 重新订购时,其他 CPU 无法弥补这一点。想象一下,如果 CPU #1 正在等待写入变量 A,然后它从变量 B 读取。如果 CPU#2 写入变量 B,则如代码所示,变量 A 不会出现问题。如果 CPU#2 重新排序首先写入变量 A,那么 CPU#1 不知道并尝试在变量 B 有值之前读取它。这可能会导致崩溃或任何 "random" 行为。 (英特尔芯片有更多的魔力让这不会发生)

Two threads being timesliced on a single CPU core won't run into a reordering problem.

如果两个线程都在同一个 CPU 上,那么写入发生的顺序无关紧要,因为如果它们被重新排序,那么它们都在进行中,并且 CPU 在两者都被写入之前不会真正切换,在这种情况下它们可以安全地从另一个线程读取。

Example

如果代码在单核上有问题,它必须重新排列来自进程 1 的两条指令 被进程 2 中断并在两者之间执行指示。但是如果在它们之间被打断,它知道它必须中止它们,因为它知道它自己的重新排序,并且知道它处于危险状态。所以它要么按顺序执行它们,要么在切换到进程 2 之前都执行,或者在切换到进程 2 之前都不执行。所有这些都避免了重新排序问题。

有多种效应在起作用,但它们被建模为只有 一个 效应。更容易推理它们。是的,现代核心已经自行重新排序指令。但它保持它们之间的逻辑流,如果两条指令之间存在相互依赖关系,那么它们将保持有序,因此程序的逻辑不会改变。发现这些相互依赖关系并防止过早发出指令是执行引擎中重新排序缓冲区的工作。

这个逻辑是可靠的,可以依靠,否则几乎不可能写出程序。但是内存控制器不能提供同样的保证。它具有让多个处理器访问同一共享内存的令人羡慕的工作。

首先是预取器,它提前从内存中读取数据,以确保在执行读取指令时数据可用。确保核心不会停止等待读取完成。问题是,由于内存被提前读取,它可能是一个陈旧的值,在预取完成和读取指令执行之间被另一个内核更改。对于外部观察者来说,它看起来像是提前执行的指令。

和存储缓冲区,它获取写入指令的数据并将其延迟写入内存。后来,指令执行后。确保核心不会停止等待内存总线写周期完成。对于外部观察者来说,它看起来像是指令执行得晚了。

将预取器和存储缓冲区的效果建模为指令重新排序效果非常方便。您可以轻松地将其写在一张纸上,并推断出副作用。

对于核心本身,预取器和存储缓冲区的影响完全是良性的,它不会注意到它们。只要没有另一个核心也在改变内存内容。单核机器总是有这种保证。