当前位置: 首页 > 知识库问答 >
问题:

在重新排序时,CPU实际上是在另一条指令之前执行指令,还是仅仅是最终结果产生了这种“错觉”?

宓季同
2023-03-14

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

但有一点我不确定。假设我有以下指示:

store x
store y

假设CPU决定在存储x之前执行存储y。

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

  1. 存储x已执行,但未立即完成(将变为挂起)

所以基本上,这给人一种“错觉”,指令是无序执行的,即使没有,也只是无序完成。

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

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

store x
mfence
store y

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

  1. 存储x已执行,但未立即完成(将变为挂起)
  2. 执行mfence,现在由于此指令是内存屏障,CPU将确保在继续执行指令之前完成它之前的所有挂起操作(store x)
  3. 执行存储y

共有2个答案

章茂
2023-03-14

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

...
div %esi        # divide edx:eax by esi
mov %eax,(%ebx) # store quotient in (%ebx)
mov $1,(%ecx)   # store 1 in (%ecx)

这就是存储以不同于机器代码指定的顺序发生的情况。CPU有额外的逻辑来确保程序员通常看不到这个细节,但根据您为什么架构编程,可以存在不同的工件。

洪承天
2023-03-14

mfence不能防止无序执行
它仅确保在执行mfence之后的任何内存加载或存储之前,mfence之前的所有内存加载和存储都已序列化。

请参见:http://x86.renejeschke.de/html/file_module_x86_id_170.html

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

在任何情况下,X86在OoO内存访问方面都是有限的
x86架构确实已经内置了一些内存排序规则。
其要点是内存访问很少接受重新排序。

以下是英特尔的官方评论:http://www.cs.cmu.edu/约410-f10/doc/Intel\u Reordering\u 318147。pdf格式

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

写回(WB)内存的内存排序
*加载不会与其他加载一起重新排序,存储也不会与其他存储一起重新排序
*存储不会与旧加载一起重新排序
*加载可能会与旧存储一起重新排序到不同的位置
[…]
*加载和存储不会使用锁重新排序

回到你的问题上来

在重新排序时,CPU是否实际先执行一条指令?是的,您可以在对代码计时时看到这一点。

让我给你举个例子,假设我们有一个AMD捷豹,它可以并行执行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遵循完全相同的语义学。

 类似资料:
  • 我正试图确切地理解什么是记忆障碍。根据我目前所知,使用内存屏障(例如:mfence)来防止指令从之前到之后和从之后到之前的重新排序。 这是正在使用的内存屏障的一个示例: 现在我的问题是:mfence指令是否只是一个指示CPU以何种顺序执行指令的标记?或者,它是CPU实际执行的指令,就像它执行其他指令一样(例如:)。

  • 问题内容: 我正在寻找写两个角度指令,一个父指令和一个子指令,以创建可排序和可克隆的小部件。预期的标记是: 但是,子指令似乎在父元素之前,某个元素可用之前执行(子元素由父元素添加): 如您所见,我尝试设置优先级,但我认为由于它们位于不同的元素上,因此无法正常工作。 如何让父母先执行? 问题答案: 推理 以相反的顺序执行,这意味着子指令将在父指令之前(即深度优先)被调用。由于某种原因,这是默认行为(

  • 本文向大家介绍v-show指令算是重排吗?相关面试题,主要包含被问及v-show指令算是重排吗?时的应答技巧和注意事项,需要的朋友参考一下 当渲染树中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建,因v-show指令改变display的属性,会发生重排。

  • 因为一次只能运行一条指令,并且假设CPU只运行这个进程。多线程难道不是线程之间快速的上下文切换,给人一种并行处理的错觉,但实际上并不是在处理吗? 那么,既然CPU要执行的指令数是一样的,不管是单线程还是多线程,完成的时间不应该是一样的吗?如果是,说明多线程是并行处理的一种方式不是错的吗?

  • 我读过很多关于内存排序的文章,他们都只说CPU会重新排序加载和存储。 CPU(我对x86 CPU特别感兴趣)是否只对加载和存储进行重新排序,而不对其拥有的其余指令进行重新排序?

  • 问题内容: 在Java 7的try-with-resources中,我不知道finally块和自动关闭发生的顺序。什么顺序 问题答案: 资源在捕获或最终阻塞之前被关闭。请参阅本教程。 try-with-resources语句可以具有catch并最终阻塞,就像普通的try语句一样。在try-with- resources语句中,在声明的资源已关闭之后,将运行任何catch或finally块。 要评估