MESI 是什么?四个状态管住多核缓存一致
答案:MESI 是缓存一致性协议,用 Modified / Exclusive / Shared / Invalid 四个状态标记每个缓存行,保证多个 CPU 核各自 L1/L2 缓存里的同一地址副本保持一致。最大的性能坑是伪共享。
四个状态(一句话版)
| 状态 | 含义 | 数据在内存? |
|---|---|---|
| M Modified | 本核已改,内存是旧的 | 内存过时,本核最新 |
| E Exclusive | 独占,只有本核有副本 | 与内存一致 |
| S Shared | 多核共享副本 | 与内存一致 |
| I Invalid | 已失效,不可用 | 重新读 |
核心机制:任何核要写一个缓存行,必须先让它成为 Exclusive(向其他核发 Invalidate 消息,令其副本转 Invalid);任何核要读,若别的核有 Modified 副本,必须等它写回。
伪共享:MESI 最常见的性能坑
// 反例:thread_a 只碰 a,thread_b 只碰 b,却互相拖慢
struct { int a; int b; } s; // a、b 在同一 64 字节缓存行!- a、b 同处一个缓存行,线程 A 改 a → 该行变 M,线程 B 的副本失效;
- 线程 B 改 b → 再次失效 A 的副本;
- 结果:两个线程频繁互踢缓存行,性能暴跌数倍。
解决:__attribute__((aligned(64)))、补 padding 到缓存行大小、或按线程拆分结构体。
深度入口
- 完整原理与协议演化:MESI 缓存一致性协议
- 缓存组织与 cache line:缓存组织
- 原子操作与一致性:原子操作
FAQ
Q: MESI 是什么? A: MESI 是缓存一致性协议,用 Modified(已改)、Exclusive(独占)、Shared(共享)、Invalid(失效)四个状态,保证多个 CPU 核的缓存副本保持一致。
Q: MESI 为什么需要? A: 多核 CPU 各自有 L1/L2 缓存,同一个内存地址可能在多个核的缓存里都有副本。如果没有一致性协议,一个核改了值,其他核还在用旧值。
Q: 伪共享(false sharing)是什么? A: 两个线程修改同一缓存行(通常 64 字节)里的不同变量,本互不相干,但 MESI 会来回失效整行缓存,导致性能暴跌。
Q: MESI 和 MOESI、MESIF 有什么区别? A: MOESI 增加了 Owned 状态(缓存行被修改但内存不是最新),MESIF 增加了 Forward 状态(转发源),用于减少跨核传输开销。
Q: 伪共享怎么避免? A: 让不同线程的变量对齐到不同缓存行:用 __attribute__((aligned(64)))、padding 到 64 字节,或按线程拆分成独立结构体。
Q: 原子操作和 MESI 有什么关系? A: 原子操作(如 lock xadd)借助缓存一致性协议保证"读-改-写"原子性:先独占缓存行(Invalidate 其他核),再修改,最后回写。
一句话总结:MESI 用 M/E/S/I 四状态管住多核缓存一致,本质是"写前独占、读时一致";实际优化中最该防的是把互不相干的变量塞进同一个缓存行造成的伪共享。