- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在互联网上我经常发现 LFENCE
在 x86 处理器中没有任何意义,即它什么都不做,所以相反 MFENCE
我们可以绝对轻松地使用 SFENCE
,因为 MFENCE
= SFENCE
+ LFENCE
= SFENCE
+ NOP
= SFENCE
。
但是如果 LFENCE
没有意义,那么为什么我们有四种方法来在 x86/x86_64 中实现顺序一致性:
LOAD
(无围栏)和STORE
+ MFENCE
LOAD
(无围栏)和LOCK XCHG
MFENCE
+ LOAD
和 STORE
(无栅栏)LOCK XADD
( 0 ) 和 STORE
(无栅栏)取自这里:http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
以及第 34 页底部 Herb Sutter 的表演:https://skydrive.live.com/view.aspx?resid=4E86B0CF20EF15AD!24884&app=WordPdf&wdo=2&authkey=!AMtj_EflYn2507c
如果LFENCE
没有做任何事情,那么方法(3)将具有以下含义:SFENCE + LOAD和STORE(没有栅栏)
,但是没有点在LOAD
之前执行SFENCE
。即,如果 LFENCE 不执行任何操作,则方法 (3) 没有意义。
指令 LFENCE
在 x86/x86_64 处理器中有意义吗?
答案:
1. LFENCE
在下面接受的答案中描述的情况下是必需的。
2. 方法(3)不应单独看待,而应与前面的命令结合起来看待。例如方法(3):
MFENCE
MOV reg, [addr1] // LOAD-1
MOV [addr2], reg //STORE-1
MFENCE
MOV reg, [addr1] // LOAD-2
MOV [addr2], reg //STORE-2
我们可以将方法(3)的代码重写如下:
SFENCE
MOV reg, [addr1] // LOAD-1
MOV [addr2], reg //STORE-1
SFENCE
MOV reg, [addr1] // LOAD-2
MOV [addr2], reg //STORE-2
这里 SFENCE
可以防止对 STORE-1 和 LOAD-2 重新排序。为此,在 STORE-1 命令 SFENCE
后刷新 Store-Buffer。
最佳答案
底线(TL;DR):单独使用 LFENCE
似乎对于内存排序毫无用处,但它并不能使 SFENCE
替代 MFENCE
。问题中的“算术”逻辑不适用。
以下摘录自 Intel's Software Developers Manual, volume 3 的第 8.2.2 节(2014 年 9 月的版本 325384-052US),与我在 another answer 中使用的内容相同
- Reads are not reordered with other reads.
- Writes are not reordered with older reads.
- Writes to memory are not reordered with other writes, with the following exceptions:
- writes executed with the CLFLUSH instruction;
- streaming stores (writes) executed with the non-temporal move instructions (MOVNTI, MOVNTQ, MOVNTDQ, MOVNTPS, and MOVNTPD); and
- string operations (see Section 8.2.4.1).
- Reads may be reordered with older writes to different locations but not with older writes to the same location.
- Reads or writes cannot be reordered with I/O instructions, locked instructions, or serializing instructions.
- Reads cannot pass earlier LFENCE and MFENCE instructions.
- Writes cannot pass earlier LFENCE, SFENCE, and MFENCE instructions.
- LFENCE instructions cannot pass earlier reads.
- SFENCE instructions cannot pass earlier writes.
- MFENCE instructions cannot pass earlier reads or writes.
从这里可以看出:
MFENCE
是针对所有内存类型(无论是否非临时)的所有操作的完整内存栅栏。 SFENCE
仅防止写入重新排序(换句话说,它是 StoreStore 屏障),并且仅与非临时存储和列为异常(exception)的其他指令一起使用。LFENCE
防止对后续读取和写入进行重新排序(即它结合了 LoadLoad 和 LoadStore 屏障)。然而,前两个要点表示 LoadLoad 和 LoadStore 屏障始终就位,没有异常(exception)。因此,单独使用 LFENCE
对于内存排序来说是没有用的。为了支持最后一个说法,我查看了英特尔手册的所有 3 卷中提到 LFENCE
的所有地方,没有发现任何地方都表明内存一致性需要 LFENCE
。甚至 MOVNTDQA
(迄今为止唯一的非临时加载指令)也提到了 MFENCE
,但没有提到 LFENCE
。
更新:请参阅 Why is (or isn't?) SFENCE + LFENCE equivalent to MFENCE? 上的答案,了解以下猜测的正确答案
MFENCE
是否等于其他两个栅栏的“总和”是一个棘手的问题。乍一看,在三个栅栏指令中,只有 MFENCE
提供 StoreLoad 屏障,即防止对较早写入的读取进行重新排序。然而,正确答案需要了解的不仅仅是上述规则;也就是说,重要的是所有栅栏指令都是相互关联的。这使得 SFENCE LFENCE
序列比单纯的单个效果的联合更强大:该序列还可以防止 StoreLoad 重新排序(因为加载无法传递 LFENCE
,而后者又无法传递 SFENCE
,后者又无法传递存储),因此构成了一个完整的内存栅栏(还请参阅下面的注释 (*))。但请注意,这里的顺序很重要,并且 LFENCE SFENCE
序列不具有相同的协同效应。
但是,虽然可以说 MFENCE ~ SFENCE LFENCE
和 LFENCE ~ NOP
,但这并不意味着 MFENCE ~ SFENCE
。我故意使用等价(~)而不是相等(=)来强调算术规则在这里不适用。 SFENCE
和 LFENCE
的相互作用会产生差异;即使负载不会相互重新排序,也需要 LFENCE
来防止使用 SFENCE
重新排序负载。
(*) 说 MFENCE
比其他两个栅栏的组合更强仍然可能是正确的。特别是,英特尔手册第 2 卷中对 CLFLUSH
指令的注释指出“CLFLUSH
仅由 MFENCE
指令排序。不保证由任何其他防护或序列化指令或其他指令排序。 CLFLUSH
说明。”
(更新,clflush
现在被定义为强有序(就像普通存储一样,因此如果您想阻止稍后加载,则只需要 mfence
),但 clflushopt
是弱有序的已订购,但可以通过 sfence
进行隔离。)
关于assembly - 在 x86/x86_64 处理器上使用 LFENCE 指令是否有意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20316124/
在最近的英特尔 ISA 文档中,lfence 指令已被定义为序列化指令流(防止跨指令流乱序执行)。特别是description该指令包括这一行: Specifically, LFENCE does n
我试图了解在使用 RDTSC/RDTSCP 测量时间时使用围栏的正确方法。关于与此相关的 SO 的几个问题已经得到了详尽的回答。我已经经历了其中的一些。我还浏览了这篇关于同一主题的非常有用的文章: h
正如我们从之前对 Does it make any sense instruction LFENCE in processors x86/x86_64? 的回答中了解到的那样我们不能使用 SFENCE
有谁知道为什么建议 LFENCE 指令在 Spectre #1(边界检查绕过/越界读取)的情况下停止推测执行,但在 Spectre #2(分支目标注入(inject))的情况下没用?这两个 Spect
在互联网上我经常发现 LFENCE 在 x86 处理器中没有任何意义,即它什么都不做,所以相反 MFENCE 我们可以绝对轻松地使用 SFENCE,因为 MFENCE = SFENCE + LFENC
好的,我一直在阅读 SO 关于 x86 CPU 栅栏的以下问题( LFENCE 、 SFENCE 和 MFENCE ): Does it make any sense instruction LFEN
据我所知,相对于rdtsc和rdtscp指令,处理器中的运行时排序的主要区别在于执行是否要等到所有先前的指令都在本地执行后才能执行。 换句话说,这意味着lfence + rdtsc = rdtscp,
简而言之,是否可以使用以下代码将src中存储的数据正确复制到dst中? volatile bool flag = false; // In thread A. memset(mid, src, siz
我是一名优秀的程序员,十分优秀!