【问题标题】:How cpu use 'mfence' to protect sequential-consistency?cpu如何使用'mfence'来保护顺序一致性?
【发布时间】:2018-11-01 05:10:35
【问题描述】:

我想知道cpu如何使用'mfence'来保护顺序一致性,谁能告诉我?

【问题讨论】:

标签: c++11 x86 cpu atomic


【解决方案1】:

为了对齐加载和存储的顺序一致性,在 x86 上足够在每个存储之后使用 mfence 指令。但是,这不是必需的:更激进的方法只需要确保在每对可能的存储和后续加载指令之间出现mfence 指令。例如,一系列未被加载中断的存储指令不需要任何mfence,除非在最终存储之后。

如果您想以原子方式执行复合操作(例如递增值),您需要的不仅仅是 mfence - 您还需要锁定指令,例如 lock inc。这也意味着与mfence 相同的屏障,因此在这种情况下不需要额外的屏障。

在实践中,mfence 可能不是强制执行顺序一致性的理想选择,即使对于普通存储而言也是如此,因为它的性能似乎比锁定操作差,因此可以使用例如 lock xchg 代替它。

【讨论】:

  • 不幸的是(?) gcc 将 C++11 atomic_var = 1 编译为 mov dword [atomic_var], 1 / mfence,而不是 mov eax, 1 / xchg [atomic_var], eax。 IDK,如果编译器开发人员对此进行了测试,或者他们使用什么基准/微基准来决定此代码生成策略。使用-mno-sse,我想它确实会使用xchg
  • @PeterCordes - 是的,我记得。我的评论可能适用于在 C++ 原子之前做这些事情的人,比如当操作本身并不需要原子操作时,Java 肯定使用了“虚拟锁定操作”方法。我也不确定为什么 gcc 以这种方式编译它。 mfence 今天实际上变慢了,这可能是完全错误的:那些主要基于背靠背测试,可能是当它看起来是更稀疏的代码时,它更快(例如,它更少 uops) .我将答案编辑为“可能不理想”而不是“通常不使用”。
【解决方案2】:

基本上,它所做的只是刷新任何读取或写入内存的操作的当前指令队列,并停止处理任何读取或写入内存的新指令,直到刷新完成。

在实践中,指令处理流水线的各个部分:解码、调度、地址计算、页面管理等都可以执行,只要内存没有被修改,并且可以允许对寄存器进行任何读取或写入,所以它不是t 和完全冲洗一样糟糕。

至于他们是如何在硅中实现的……不知道。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-13
  • 2018-04-04
  • 2015-05-08
相关资源
最近更新 更多