gpt4 book ai didi

assembly - 为什么(或不是?)SFENCE + LFENCE 等价于 MFENCE?

转载 作者:行者123 更新时间:2023-12-04 13:19:12 28 4
gpt4 key购买 nike

正如我们从之前对 Does it make any sense instruction LFENCE in processors x86/x86_64? 的回答中了解到的那样我们不能使用 SFENCE而不是 MFENCE顺序一致性。

那里的答案表明 MFENCE = SFENCE + LFENCE ,即 LFENCE做了一些我们无法提供顺序一致性的事情。
LFENCE无法重新排序:

SFENCE
LFENCE
MOV reg, [addr]

-- 到 -->
MOV reg, [addr]
SFENCE
LFENCE

例如重新排序 MOV [addr], reg LFENCE --> LFENCE MOV [addr], reg 提供机制 - 存储缓冲区 ,它重新排序 Store - Loads 以提高性能,并且因为 LFENCE不阻止它。和 SFENCE 禁用此机制 .

什么机制禁用了 LFENCE使不可能的重新排序(x86 没有机制 - 无效队列)?

并且正在重新排序 SFENCE MOV reg, [addr] --> MOV reg, [addr] SFENCE仅在理论上可能还是在现实中可能?如果可能的话,实际上是什么机制,它是如何工作的?

最佳答案

x86围栏指令可以简单描述如下:

  • MFENCE 防止任何较晚的加载或存储在任何较早的加载或存储之前变得全局可见。它在以后的 load1 可以执行之前排空存储缓冲区。
  • LFENCE 会阻止指令分派(dispatch)(Intel 的术语),直到所有较早的指令都失效。这目前是通过在以后的指令可以发布到后端之前排空 ROB(重新排序缓冲区)来实现的。
  • SFENCE 仅针对其他存储对存储进行排序,即防止 NT 存储在 SFENCE 本身之前从存储缓冲区提交。但除此之外,SFENCE 就像一个在存储缓冲区中移动的普通存储。把它想象成在杂货店结账传送带上放置一个分隔器,可以防止 NT 商店过早被抢购。在从 ROB 退出之前,它不一定会强制排空存储缓冲区,因此将 LFENCE 放在它之后不会加起来等于 MFENCE。
  • 像 CPUID(和 IRET 等)这样的“序列化指令”在后续指令可以发布到后端之前耗尽所有内容(ROB、存储缓冲区)。 MFENCE + LFENCE 也会这样做,但真正的序列化指令可能还有其他效果,我不知道。

  • 这些描述在订购什么样的操作方面有点含糊不清,并且供应商之间存在一些差异(例如,SFENCE 在 AMD 上更强),甚至来自同一供应商的处理器。有关详细信息,请参阅 Intel 的手册和规范更新以及 AMD 的手册和修订指南。在 SO 其他其他地方也有很多关于这些说明的其他讨论。但请先阅读官方资料。上面的描述是我认为跨供应商的最小指定的纸上行为。
    脚注 1 : 后面store的OoO exec不需要被MFENCE屏蔽;执行它们只是将数据写入存储缓冲区。按顺序提交已经在较早的存储之后对它们进行了订购,并在停用订单之后提交。加载(因为 x86 要求加载完成,而不仅仅是启动,然后才能退休,作为确保加载顺序的一部分)。
    请记住,x86 硬件旨在禁止除 StoreLoad 之外的重新排序。
    英特尔手册第 2 卷编号 325383-072US 将 SFENCE 描述为“确保在 SFENCE 之后的任何存储变得全局可见之前,SFENCE 之前的每个存储都是全局可见的”。第 3 卷第 11.10 节说使用 SFENCE 时会耗尽存储缓冲区。对这条语句的正确解释正是第 2 卷中较早的语句。因此可以说 SFENCE 在这个意义上耗尽了存储缓冲区。无法保证在 SFENCE 的生命周期中较早的商店在什么时候实现 GO。对于任何较早的商店,它可能发生在 SFENCE 退休之前、之时或之后。关于 GO 的意义是什么,它取决于几个因素。这超出了问题的范围。见: Why “movnti” followed by an “sfence” guarantees persistent ordering? .
    MFENCE 确实必须防止 NT 存储与其他存储重新排序,因此它必须包括 SFENCE 所做的任何事情,以及排空存储缓冲区。并且还对来自 WC 内存的弱排序 SSE4.1 NT 加载进行重新排序,这更加困难,因为免费获得加载排序的正常规则不再适用于那些。保证这个 is why a Skylake microcode update strengthened (and slowed) MFENCE也像LFENCE一样耗尽ROB。 MFENCE 仍然有可能比硬件支持更轻,以选择性地强制执行管道中 NT 负载的排序。

    SFENCE + LFENCE 不等于MFENCE 的主要原因是因为SFENCE + LFENCE 不会阻塞StoreLoad 重新排序,因此不足以实现顺序一致性 .只有 mfence (或 lock ed 操作,或真正的序列化指令,如 cpuid )将做到这一点。参见 Jeff Preshing 的 Memory Reordering Caught in the Act对于只有完整屏障就足够的情况。

    来自 Intel's instruction-set reference manual entry for sfence :

    The processor ensures that every store prior to SFENCE is globally visible before any store after SFENCE becomes globally visible.



    It is not ordered with respect to memory loads or the LFENCE instruction.



    LFENCE 强制较早的指令“在本地完成”(即从核心的乱序部分退出),但对于存储或 SFENCE 而言,这仅意味着将数据或标记放入内存顺序缓冲区中,而不是将其刷新商店变得全局可见。即 SFENCE“完成”(从 ROB 退休)不包括刷新存储缓冲区。
    这就像 Preshing 在 Memory Barriers Are Like Source Control Operations 中描述的一样,其中 StoreStore 障碍不是“即时”的。在那篇文章的后面,他解释了为什么#StoreStore + #LoadLoad + #LoadStore 屏障加起来不等于#StoreLoad 屏障。 (x86 LFENCE 有一些额外的指令流序列化,但由于它不刷新存储缓冲区,推理仍然成立)。
    LFENCE 没有像 cpuid 那样完全序列化 ( which is as strong a memory barrier as mfence or a lock ed instruction )。它只是 LoadLoad + LoadStore 屏障,加上一些执行序列化的东西,这些东西可能是作为一个实现细节开始的,但现在被奉为保证,至少在 Intel CPU 上是这样。它对 rdtsc 很有用,并避免分支推测以减轻 Spectre。

    顺便说一句,SFENCE 是 WB(普通)商店的空缺。
    它根据任何存储对 WC 存储(例如 movnt 或存储到视频 RAM)进行排序,但与加载或 LFENCE 无关。只有在通常弱排序的 CPU 上,商店-商店屏障才能为正常商店做任何事情。除非您使用 NT 存储或映射 WC 的内存区域,否则您不需要 SFENCE。如果它确实保证在它可以退休之前耗尽存储缓冲区,那么您可以使用 SFENCE+LFENCE 构建 MFENCE,但英特尔的情况并非如此。

    真正关心的是 StoreLoad 在商店和负载之间重新排序,而不是在商店和屏障之间,所以 你应该看看一个带有商店的案例,然后是障碍物,然后是负载 .
    mov  [var1], eax
    sfence
    lfence
    mov eax, [var2]
    可以按以下顺序全局可见(即提交到 L1d 缓存):
    lfence
    mov eax, [var2] ; load stays after LFENCE

    mov [var1], eax ; store becomes globally visible before SFENCE
    sfence ; can reorder with LFENCE

    关于assembly - 为什么(或不是?)SFENCE + LFENCE 等价于 MFENCE?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27627969/

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