gpt4 book ai didi

assembly - 在 x86/x86_64 处理器上使用 LFENCE 指令是否有意义?

转载 作者:行者123 更新时间:2023-12-02 06:47:11 29 4
gpt4 key购买 nike

在互联网上我经常发现 LFENCE 在 x86 处理器中没有任何意义,即它什么都不做,所以相反 MFENCE 我们可以绝对轻松地使用 SFENCE,因为 MFENCE = SFENCE + LFENCE = SFENCE + NOP = SFENCE

但是如果 LFENCE 没有意义,那么为什么我们有四种方法来在 x86/x86_64 中实现顺序一致性:

  1. LOAD(无围栏)和STORE + MFENCE
  2. LOAD(无围栏)和LOCK XCHG
  3. MFENCE + LOADSTORE(无栅栏)
  4. 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 LFENCELFENCE ~ NOP ,但这并不意味着 MFENCE ~ SFENCE 。我故意使用等价(~)而不是相等(=)来强调算术规则在这里不适用。 SFENCELFENCE 的相互作用会产生差异;即使负载不会相互重新排序,也需要 LFENCE 来防止使用 SFENCE 重新排序负载。

(*) 说 MFENCE 比其他两个栅栏的组合更强仍然可能是正确的。特别是,英特尔手册第 2 卷中对 CLFLUSH 指令的注释指出“CLFLUSH 仅由 MFENCE 指令排序。不保证由任何其他防护或序列化指令或其他指令排序。 CLFLUSH 说明。”

(更新,clflush 现在被定义为强有序(就像普通存储一样,因此如果您想阻止稍后加载,则只需要 mfence),但 clflushopt 是弱有序的已订购,但可以通过 sfence 进行隔离。)

关于assembly - 在 x86/x86_64 处理器上使用 LFENCE 指令是否有意义?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20316124/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com