首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当重新排序时,CPU实际上是先执行另一个指令,还是只有最终结果才会产生这种“幻觉”?

当重新排序时,CPU实际上是先执行另一个指令,还是只有最终结果才会产生这种“幻觉”?
EN

Stack Overflow用户
提问于 2017-03-11 01:00:43
回答 2查看 222关注 0票数 1

基于我所读到的,CPU可以重新排序指令的执行,而内存屏障可以防止指令从前到后以及从后到后的重新排序。

但有件事我不确定。假设我有以下说明:

代码语言:javascript
复制
store x
store y

假设CPU决定在store y之前执行store x

CPU是如何做到这一点的,它是否完全忽略store x并首先执行store y?或者会发生以下情况:

  1. store x被执行,但它没有立即完成(它将被挂起)。
  2. store y被执行,并立即完成。
  3. 挂起的store x已经完成。

因此,基本上,这给了一种“错觉”,即指令被不正常地执行,即使没有,他们只完成了无序。

我问这个问题是为了了解记忆障碍是如何运作的。

例如,假设我有以下说明:

代码语言:javascript
复制
store x
mfence
store y

现在,当CPU执行这些指令时,会发生以下情况吗?

  1. store x被执行,但它没有立即完成(它将被挂起)。
  2. mfence被执行,因为这个指令是一个内存屏障,所以CPU将确保在继续执行指令之前,它之前的所有未决操作(store x)都将完成。
  3. store y被执行。
EN

回答 2

Stack Overflow用户

发布于 2017-03-11 10:39:21

mfence 并不阻止无序执行.

它只需确保mfence前面的所有内存负载和存储在执行任何内存负载或在mfence之后存储之前都是序列化的。

请参阅:170.html

对在MFENCE指令之前发出的所有从内存加载和存储到内存的指令执行序列化操作.此序列化操作确保在MFENCE指令之后的任何加载或存储指令全局可见之前,按程序顺序排列的每个加载和存储指令都是全局可见的。

X86 is在OoO内存访问中受到限制,在任何情况下都是

x86体系结构已经内置了一些内存排序规则。

这其中的要点是内存访问很少得到重新排序。

这是英特尔的官方报道:318147.pdf

索引中列出的最有用的要点是:-)

用于写回(WB)内存的内存排序() *负载不会与其他负载重新排序,存储也不会与其他存储重新排序。 *仓库不会随着旧货重新排序 *旧货可能被重新订购到不同的地点 ..。 *没有用锁重新排序负载和存储

回到你的问题

当重新排序时,CPU实际上在另一个之前执行指令吗? 是的,您可以在计时代码时看到这一点。

让我给你一个例子,让我们假设我们有一个美洲虎,它可以执行2个指令并行,并有完整的OoO。

代码语言:javascript
复制
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将按照以下顺序执行此操作:

代码语言:javascript
复制
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遵循完全相同的语义。

票数 3
EN

Stack Overflow用户

发布于 2017-03-11 16:37:01

在超级标量处理器上,您可以让操作排队等待以前的指令完成。想象一下这样的代码:

代码语言:javascript
复制
...
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有额外的逻辑来确保这个细节通常不会被程序员看到,但是取决于您为哪种体系结构编程,可以存在不同的工件。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42730130

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档