Chapter 05 · coherence bus chamber
内存层级
进入三核共享 cache line 的现场。每一次 Read/Write 都会改变 M/E/S/I 状态,触发 BusRd、BusRdX 或 Flush。
为什么多核共享数据这么麻烦
每个核都有自己的 L1 Cache,但内存只有一份。当多核读写同一个 cache line 时, 硬件必须保证"看到的值"对所有核一致——这就是缓存一致性 (Cache Coherence)。
下面是 1984 年 Papamarcos & Patel 提出的 MESI 协议。 每条 cache line 处于 4 个状态之一: Modified(独占且脏)、 Exclusive(独占且干净)、 Shared(共享)、 Invalid(无效)。 总线嗅探让所有核保持一致。
Click Read / Write on any core. Watch ownership, invalidation, and memory writeback happen as bus events.
L1 miss,L2 命中,12 cycles。
L1 装不下全部 working set,但 L2 仍保留该 line。
12 cycles
工程细节
False Sharing · 性能杀手
一条 cache line 通常是 64 字节。如果两个线程各自频繁写自己的变量,但这两个 变量恰好落在同一条 cache line,即使逻辑上不冲突,硬件也会让 cache line 在多核之间乒乓 (ping-pong)—— 性能可能降到单线程的 1/10。
修复:用 alignas(64) 或 手动 padding 把热点变量放到不同 cache line。
内存一致性模型 (TSO / Weak)
缓存一致性保证同一地址的多核可见性;内存一致性保证不同地址操作的可见顺序。 两件事不同。
- x86-TSO:Store-Load 可能重排,其他不重排
- ARM / RISC-V:几乎全部可重排,要靠
fence(屏障)强制顺序 - 所以 x86 上能跑对的代码,在 ARM 上可能出 race
MESI 在真实 CPU 上的变种
Intel 用 MESIF(F = Forward,指定一个"主"S 核响应总线请求); AMD 用 MOESI(O = Owned,允许"脏共享"——一个核脏 + 其他核 S 而不写回内存)。 两者都是 MESI 的演进,核心思路一致。