基于我所读到的,CPU可以重新排序指令的执行,而内存屏障可以防止指令从前到后以及从后到后的重新排序。
但有件事我不确定。假设我有以下说明:
store x
store y假设CPU决定在store y之前执行store x。
CPU是如何做到这一点的,它是否完全忽略store x并首先执行store y?或者会发生以下情况:
store x被执行,但它没有立即完成(它将被挂起)。store y被执行,并立即完成。store x已经完成。因此,基本上,这给了一种“错觉”,即指令被不正常地执行,即使没有,他们只完成了无序。
我问这个问题是为了了解记忆障碍是如何运作的。
例如,假设我有以下说明:
store x
mfence
store y现在,当CPU执行这些指令时,会发生以下情况吗?
store x被执行,但它没有立即完成(它将被挂起)。mfence被执行,因为这个指令是一个内存屏障,所以CPU将确保在继续执行指令之前,它之前的所有未决操作(store x)都将完成。store y被执行。发布于 2017-03-11 10:39:21
mfence 并不阻止无序执行.
它只需确保mfence前面的所有内存负载和存储在执行任何内存负载或在mfence之后存储之前都是序列化的。
请参阅:170.html
对在MFENCE指令之前发出的所有从内存加载和存储到内存的指令执行序列化操作.此序列化操作确保在MFENCE指令之后的任何加载或存储指令全局可见之前,按程序顺序排列的每个加载和存储指令都是全局可见的。
X86 is在OoO内存访问中受到限制,在任何情况下都是
x86体系结构已经内置了一些内存排序规则。
这其中的要点是内存访问很少得到重新排序。
这是英特尔的官方报道:318147.pdf
索引中列出的最有用的要点是:-)
用于写回(WB)内存的内存排序() *负载不会与其他负载重新排序,存储也不会与其他存储重新排序。 *仓库不会随着旧货重新排序 *旧货可能被重新订购到不同的地点 ..。 *没有用锁重新排序负载和存储
回到你的问题
当重新排序时,CPU实际上在另一个之前执行指令吗? 是的,您可以在计时代码时看到这一点。
让我给你一个例子,让我们假设我们有一个美洲虎,它可以执行2个指令并行,并有完整的OoO。
a: mov ebx,[eax] //1 cycle throughput
b: mov ecx,2 //pairs
c: imul eax,edx //3 cycles latency
d: add eax,ebp //1 cycle, needs to wait for c通常,这个片段需要1+3+1 =5个周期。但是,CPU将按照以下顺序执行此操作:
c: imul eax,edx //3 cycle latency
a: mov ebx,[eax'] //pairs, eax is renamed to eax' in the register rename buffer
b: mov ecx,2 //1 cycle
d: add eax,ebp //1 cycle waits for c这只需要4个周期。3表示a,1表示d,其余全部交错。
显然,在c和d之间有更多的指令,如果它有任何适用的指令,CPU就会这样做。
请注意,CPU重新排序一个内存负载,只要它与另一个内存负载无关(以及其他一些限制,见上文)。
还请注意,AMD和Intel遵循完全相同的语义。
发布于 2017-03-11 16:37:01
在超级标量处理器上,您可以让操作排队等待以前的指令完成。想象一下这样的代码:
...
div %esi # divide edx:eax by esi
mov %eax,(%ebx) # store quotient in (%ebx)
mov $1,(%ecx) # store 1 in (%ecx)在超级标量处理器上,第一个mov指令将在发送div指令后立即出现。然而,当时div还没有完成。因此,存储指令在指令队列中排队,直到div %esi的结果在%eax中可用为止。在下一个周期中,处理器会遇到mov $1,(%ecx)。由于立即可用的$1,处理器不需要等待,可以立即执行存储。在存储被分派之后的一段时间,div指令完成,导致存储从指令队列中释放并执行。
存储发生在与机器代码指定的顺序不同的情况下。CPU有额外的逻辑来确保这个细节通常不会被程序员看到,但是取决于您为哪种体系结构编程,可以存在不同的工件。
https://stackoverflow.com/questions/42730130
复制相似问题