内存屏障不会让其他线程看到您的存储any faster.(除了阻止以后的加载可能会稍微减少提交缓冲存储的争用。)
The store buffer always tries to commit retired (known non-speculative) stores to L1d cache as fast as possible. Cache is coherent1, so that makes them globally visible because of MESI/MESIF/MOESI. The store buffer is not designed as a proper cache or write-combining buffer (although it can combine back-to-back stores to the same cache line), so it needs to empty itself to make room for new stores. Unlike a cache, it wants to keep itself empty, not full.
Note 1:不只是x86;任何 ISA 的所有多核系统(我们可以跨其核心运行 Linux 的单个实例)都必然是缓存一致的; Linux依赖于volatile
其手工滚动原子使数据可见。类似地,C++std::atomic
加载/存储操作mo_relaxed
只是普通的 asm 加载和存储在所有普通 CPU 上,依赖硬件来实现内核之间的可见性,而不是手动刷新。何时在多线程中使用 易失性?解释说。有一些集群或混合微控制器+DSP ARM 板具有非一致性共享内存,但我们不会跨单独的一致性域运行同一进程的线程。相反,您可以在每个集群节点上运行单独的操作系统实例。我不知道有任何 C++ 实现atomic<T>
加载/存储包括手动冲洗指令。 (如果有的话请告诉我。)
栅栏/屏障的工作原理是让当前线程等待
...直到通过正常机制发生所需的任何可见性。
完整屏障的简单实现(mfence
or a lock
ed 操作)的目的是停止管道,直到存储缓冲区耗尽,但高性能实现可以做得更好,并允许与内存顺序限制分开的乱序执行。
(很遗憾天湖的mfence确实完全阻止乱序执行,修复涉及从 WC 内存加载 NT 的模糊 SKL079 勘误表。但lock add
or xchg
或任何仅阻止稍后从读取 L1d 或存储缓冲区加载的内容,直到屏障到达存储缓冲区的末尾。和mfence
在早期的 CPU 上可能也没有这个问题。)
一般来说,在非 x86 架构上(对于较弱的内存屏障有显式的 asm 指令,例如仅限 StoreStore 围栏不关心负载),原理是相同的:阻止它需要阻止的任何操作,直到该核心完成任何类型的早期操作。
Related:
-
全局不可见加载指令讨论负载变得全局可见意味着什么/负载数据来自哪里。
-
内存屏障是否确保缓存一致性已完成?
-
内存屏障是否既充当标记又充当指令?
-
何时在多线程中使用 易失性?- 基本上从不,这只是你自己的一种方式std::atomic<T>
with std::memory_order_relaxed
因为缓存一致性。
-
推测执行的 CPU 分支是否可以包含访问 RAM 的操作码?- 什么是存储缓冲区以及它们存在的原因。
最终,我试图为自己回答的问题是线程 2 是否有可能在几秒钟内看不到线程 1 的写入
不,最坏情况的延迟可能类似于存储缓冲区长度(Skylake 上有 56 个条目,而 BDW 中有 42 个条目)乘以缓存未命中延迟,因为 x86 的强内存模型(无 StoreStore 重新排序)要求存储按顺序提交。但是多个缓存行的 RFO 可以同时运行,因此最大延迟可能是其 1/5(保守估计:有 10 个行填充缓冲区)。飞行中的负载(或来自其他核心)也可能存在争用,但我们只想要一个数量级的粗略数字。
假设 RFO 延迟(DRAM 或来自另一个内核)在 3GHz CPU 上为 300 个时钟周期(基本上是弥补的)。所以一个最坏的情况下延迟商店在全球范围内可见可能是这样的300 * 56 / 5
= 3360 个核心时钟周期。所以在一个数量级内,最坏情况约为 1 微秒在我们假设的 3GHz CPU 上。 (CPU 频率相互抵消,因此以纳秒为单位估计 RFO 延迟会更有用)。
就在那时all您的商店需要等待很长时间才能收到 RFO,因为它们all到未缓存或由其他核心拥有的位置。并且它们都不是连续的同一缓存行,因此它们都不能合并到存储缓冲区中。所以通常你会期望它会快得多。
我认为没有任何合理的机制可以让它花费一百微秒,更不用说一整秒了。
如果您的所有存储都是缓存行,而其他内核都在竞争访问同一行,则您的 RFO 可能需要比正常情况更长的时间,因此可能需要数十微秒,甚至可能是一百微秒。但这种绝对最坏的情况不会偶然发生。