【发布时间】:2015-11-13 07:28:24
【问题描述】:
我认为只有字符串和(某些)流指令需要 Intel x86 上的内存屏障?对于所有其他指令,英特尔强内存排序模型可确保实现一致性?
假设以上是正确的,当我们的代码只在 Intel x86 上执行时,为什么我们需要使用 C++ 原子(不包括比较和交换)?
我真的让自己感到困惑,我们需要在哪里使用原子,以及使用原子是否会由于内存障碍以及整个 MESI 协议而抑制乱序执行。
MESI 只是确保缓存在所有处理器之间保持一致?
内存屏障在其他架构上很有用,因为它们会将 CPU 存储缓冲区刷新到缓存中,以允许 MESI 确保一致性?
我们什么时候需要在 Intel X86 CPU 上使用原子?
【问题讨论】:
-
假设以上是正确的 - 它不是。即使是获取/释放语义,英特尔也需要障碍。 x86 为实际编程提供了令人难以置信的昂贵且同时仍然相当有限的排序保证。基本上你需要一个用于 StoreLoad 屏障的屏障(mfence,锁定指令)。
-
@Voo:我不是专家,但 AFAIK 并不经常需要 StoreLoad 屏障。我不明白如何将 x86 内存排序描述为“相当有限的实际编程”。对于实际编程I 通常需要发布/获取语义,英特尔提供的语义没有任何明确的障碍。
-
@Voo:IDK 如果我们谈论的是同一件事。我所说的是具有获取语义的操作和具有释放语义的操作。它既不需要 StoreLoad 屏障也不需要完整的栅栏。并且 GCC 不会在
std::atomic<int>::store(x, memory_order_release)之后生成 mfence。见goo.gl/XcozsM -
@Voo:mfence 当然是完整屏障所必需的。获取/释放不需要完整的屏障。因此,获取/释放不需要 mfence。这并不意味着它完全没用。这只意味着我们不需要它,只要我们可以只用获取和释放语义来做我们需要的事情。 ps:更好的例子,包括获取和释放之间的负载:goo.gl/oJjVXG
标签: c++ multithreading assembly concurrency atomic