multithreading - 假设没有非临时指令,“xchg”是否包含“mfence”?
问题描述
我已经看过这个答案和这个答案,但在没有非临时指令的假设下,两者似乎都没有明确和明确的等价或不等价mfence
。xchg
英特尔指令参考xchg
提到该指令对于实现信号量或类似的进程同步数据结构很有用,并进一步参考了第 3A 卷的第 8 章。该参考说明如下。
对于 P6 系列处理器,锁定操作会序列化所有未完成的加载和存储操作(即等待它们完成)。此规则也适用于 Pentium 4 和 Intel Xeon 处理器,但有一个例外。引用弱排序内存类型(如 WC 内存类型)的加载操作可能不会被序列化。
该mfence
文档声称以下内容。
对在 MFENCE 指令之前发出的所有从内存加载和存储到内存指令执行序列化操作。这种序列化操作保证了在程序顺序中位于 MFENCE 指令之前的每个加载和存储指令在 MFENCE 指令之后的任何加载或存储指令之前变得全局可见。1 MFENCE 指令相对于所有加载和存储指令、其他 MFENCE 指令、任何 LFENCE 和 SFENCE 指令以及任何序列化指令(例如 CPUID 指令)进行排序。MFENCE 不序列化指令流。
如果我们忽略弱排序的内存类型,xchg(这意味着lock
)是否包含 mfence 关于内存排序的所有保证?
解决方案
假设您没有编写设备驱动程序(因此所有内存都是回写,而不是弱排序的写入组合),那么yesxchg
与mfence
.
NT商店很好。
我确信当前的硬件就是这种情况,并且相当肯定的是,所有未来 x86 CPU 的手册中的措辞都保证了这一点。 xchg
是一个非常强大的全内存屏障。
嗯,我还没有看过预取指令重新排序。这可能与性能有关,甚至可能与奇怪的设备驱动程序情况下的正确性有关(您可能不应该使用可缓存内存)。
从你的报价:
(P4/Xeon) 引用弱排序内存类型(如WC内存类型)的加载操作可能不会被序列化。
那是当时变得更xchg [mem]
弱的一件事mfence
(在 Pentium4 上?可能也在 Sandybridge-family 上)。
mfence
确实保证了这一点,这就是为什么 Skylake 必须加强它以修复错误。(加载和存储是唯一被重新排序的指令吗?以及您链接的答案是否锁定 xchg 与 mfence 具有相同的行为?)
NT 存储由xchg
/序列化lock
,它只是可能无法序列化的弱排序加载。 您不能从 WB memory 执行弱排序加载。 movntdqa xmm, [mem]
WB 内存仍然是强排序的(并且在当前的实现中,也忽略了 NT 提示,而不是做任何事情来减少缓存污染)。
在当前 CPU 上, seq-cst 存储的性能似乎xchg
比mov
+更好mfence
,因此您应该在普通代码中使用它。(您不会意外映射 WC 内存;普通操作系统总是会为您提供 WB 内存以进行正常分配。WC 仅用于视频 RAM 或其他设备内存。)
这些保证是根据特定的英特尔微架构系列指定的。如果我们可以为未来的 Intel 和 AMD CPU 提供一些常见的“基准 x86”保证,那就太好了。
我假设但尚未检查xchg
AMD的mfence
情况是否相同。我确信xchg
用作 seq-cst 存储没有正确性问题,因为这是 gcc 以外的编译器实际上所做的。
推荐阅读
- maven-3 - 如何让 Maven 依赖项从父 pom 传播到子模块?
- r - 如何标记一个值出现在 R 中多个组中的行?
- c++ - 无法将 sndfile 库链接到 cmake 项目(MacOS)
- c# - 带有其他按钮列表的按钮 C#
- css - Gulp 4 和 Browsersync:错误:找不到要导入的文件或无法读取
- javascript - 在 reactjs 中 click() 和 dispatchEvent 都不会触发自动点击
- javascript - 编写正确的 FormData 请求
- javascript - 通过 Azure Devops 管道运行 cypress 测试 访问 URL 后出现“抱歉,我们无法加载”错误
- c++ - 使用 const 字面量的初学者 C++ 投票程序
- c# - 将 DataTemplate 中标签的 TextColor 的颜色与资源相关联