【发布时间】:2018-11-01 05:10:35
【问题描述】:
我想知道cpu如何使用'mfence'来保护顺序一致性,谁能告诉我?
【问题讨论】:
-
preshing.com/20120515/memory-reordering-caught-in-the-act:
mfence是 StoreLoad 重新排序的障碍。
我想知道cpu如何使用'mfence'来保护顺序一致性,谁能告诉我?
【问题讨论】:
mfence 是 StoreLoad 重新排序的障碍。
为了对齐加载和存储的顺序一致性,在 x86 上足够在每个存储之后使用 mfence 指令。但是,这不是必需的:更激进的方法只需要确保在每对可能的存储和后续加载指令之间出现mfence 指令。例如,一系列未被加载中断的存储指令不需要任何mfence,除非在最终存储之后。
如果您想以原子方式执行复合操作(例如递增值),您需要的不仅仅是 mfence - 您还需要锁定指令,例如 lock inc。这也意味着与mfence 相同的屏障,因此在这种情况下不需要额外的屏障。
在实践中,mfence 可能不是强制执行顺序一致性的理想选择,即使对于普通存储而言也是如此,因为它的性能似乎比锁定操作差,因此可以使用例如 lock xchg 代替它。
【讨论】:
atomic_var = 1 编译为 mov dword [atomic_var], 1 / mfence,而不是 mov eax, 1 / xchg [atomic_var], eax。 IDK,如果编译器开发人员对此进行了测试,或者他们使用什么基准/微基准来决定此代码生成策略。使用-mno-sse,我想它确实会使用xchg。
mfence 今天实际上变慢了,这可能是完全错误的:那些主要基于背靠背测试,可能是当它看起来是更稀疏的代码时,它更快(例如,它更少 uops) .我将答案编辑为“可能不理想”而不是“通常不使用”。
基本上,它所做的只是刷新任何读取或写入内存的操作的当前指令队列,并停止处理任何读取或写入内存的新指令,直到刷新完成。
在实践中,指令处理流水线的各个部分:解码、调度、地址计算、页面管理等都可以执行,只要内存没有被修改,并且可以允许对寄存器进行任何读取或写入,所以它不是t 和完全冲洗一样糟糕。
至于他们是如何在硅中实现的……不知道。
【讨论】:
mfence 不在指令流上序列化,仅在内存操作上进行序列化,它确保存储已提交到 L1d,而不仅仅是在指令流中本地执行。