Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 记忆障碍是否既作为标记又作为指令?_Assembly_X86_Cpu Architecture_Instruction Set_Memory Barriers - Fatal编程技术网

Assembly 记忆障碍是否既作为标记又作为指令?

Assembly 记忆障碍是否既作为标记又作为指令?,assembly,x86,cpu-architecture,instruction-set,memory-barriers,Assembly,X86,Cpu Architecture,Instruction Set,Memory Barriers,我读过关于记忆障碍如何工作的不同文章 例如,用户Johan在中的回答说,内存屏障是CPU执行的指令 而用户Peter Cordes在中的评论是关于CPU如何重新排序指令的: 它的读取速度比执行速度快,因此可以看到 即将发布的指令。有关详细信息,请参阅x86中的一些链接 标记wiki,如Agner Fog的Microach pdf,以及David Kanter的 英特尔Haswell设计的编写。当然,如果你只是 谷歌搜索“无序执行”,你会发现维基百科的文章, 你应该读一读 因此,我根据上面的评论猜

我读过关于记忆障碍如何工作的不同文章

例如,用户Johan在中的回答说,内存屏障是CPU执行的指令

而用户Peter Cordes在中的评论是关于CPU如何重新排序指令的:

它的读取速度比执行速度快,因此可以看到 即将发布的指令。有关详细信息,请参阅x86中的一些链接 标记wiki,如Agner Fog的Microach pdf,以及David Kanter的 英特尔Haswell设计的编写。当然,如果你只是 谷歌搜索“无序执行”,你会发现维基百科的文章, 你应该读一读

因此,我根据上面的评论猜测,如果指令之间存在内存障碍,CPU将看到这个内存障碍,这导致CPU不会对指令重新排序,因此这意味着内存障碍是CPU可以看到而不能执行的“标记”


现在我猜测内存屏障既可以作为标记,也可以作为CPU执行的指令

对于标记部分,CPU会看到指令之间的内存屏障,这会导致CPU不会对指令重新排序

至于指令部分,CPU将执行内存屏障指令,这会导致CPU执行诸如刷新存储缓冲区之类的操作,然后CPU将在内存屏障之后继续执行指令

我说的对吗?

不,
mfence
没有在指令流上序列化,并且
lfence
(即)没有刷新存储缓冲区。 (在Skylake上的实践中,
mfence
确实阻止了后续ALU指令的无序执行,而不仅仅是加载。()。因此,它被实现为一个执行障碍,即使在纸面上不要求它是一个。但是
lock xchg
不需要,而且也是一个完整的障碍。)

我建议阅读杰夫·普雷辛的文章,更好地了解记忆障碍需要做什么,不需要做什么。它们通常不(需要)阻止无序执行


内存障碍限制了内存操作全局可见的顺序,而不是(必要的)指令执行的顺序。再次阅读@BeeOnRope对上一个问题的更新答案:要了解更多关于在没有OoO exec的情况下如何进行内存重排序的信息,以及OoO exec如何在没有内存重新排序的情况下发生

暂停管道和刷新缓冲区是实现屏障的一种(低性能)方法,但具有更多内存顺序跟踪功能的高性能CPU可能具有更便宜的内存屏障,仅限制内存操作的顺序,而不是所有指令。对于内存操作,它们控制对L1d缓存的访问顺序(在存储缓冲区的另一端),而不一定是存储将数据写入存储缓冲区的顺序

x86已经需要大量的内存顺序跟踪来实现正常加载/存储,以获得高性能,同时保持其强顺序内存模型,只有内核外的观察者才能看到该模型(即,存储可以在以后加载之前进行缓冲)。(英特尔的《优化手册》使用“内存顺序缓冲区”(Memory Order Buffer,简称MOB)一词代替“存储缓冲区”,因为它还必须跟踪加载顺序。如果发现推测性加载占用数据太早,它必须清除内存顺序机。)现代x86 CPU保留了尊重内存模型的假象,同时实际执行无序加载和存储

mfence
只需将一个标记写入内存顺序缓冲区即可完成其工作,而不会成为以后ALU指令无序执行的障碍。在
mfence
标记到达存储缓冲区的末尾之前,此标记必须至少防止执行后续加载。(以及在弱有序WC内存上对NT存储和操作进行排序)

(但同样,更简单的行为是一种有效的实现选择,例如,在所有早期加载失效且早期存储已提交到L1d缓存之前,不允许
mfence
之后的任何存储将数据写入存储缓冲区。即,完全耗尽MOB/store缓冲区。我不知道当前Intel或AMD CPU的具体操作。)


具体来说,在Skylake上,
mfence
是前端(融合域)的4个UOP,以及在执行端口上实际执行的2个UOP(一个用于端口2/3(加载/存储地址),另一个用于端口4(存储数据))。它可能是一种特殊的uop,将标记写入内存顺序缓冲区。不需要执行单元的2个UOP可能类似于
lfence
。我不确定他们是否会阻止前端在以后加载,但希望不会,因为这会阻止以后独立的ALU操作的执行


lfence
是一个有趣的例子:除了作为LoadLoad+LoadStore屏障(即使对于弱有序的加载;正常的加载/存储已经有序),也是一个弱执行屏障(请注意,
mfence
不是,只是
lfence
)。在所有早期指令“本地完成”之前,它无法执行。这大概意味着从无序核心“退休”

但是,存储在退出之前无法提交L1d缓存(即,在已知它是非推测性的之后),因此等待存储从ROB(UOP的重新排序缓冲区)退出与等待存储缓冲区清空不是一回事。看

因此,是的,CPU管道在执行之前必须“注意”
lfence
,可能是在发布/重命名阶段。我的理解是,
lfence
在ROB为空之前不能发行。(在英特尔CPU上,
lfence