Lec 12缓存一致性(Cache Coherence)
Lec 12 缓存一致性(Cache Coherence)
MIT 6.5900 Fall 2024 · Daniel Sanchez 主题:多核动机与 Amdahl 定律、通信模型、一致性 vs 一致、侦听式协议(VI/MSI/MESI/MOESI)、同步与原子操作
TL;DR
- 一致性核心契约:共享内存多核系统通过写传播(Write Propagation)与写串行化(Write Serialization)两大不变量维持单一内存视图。
- 侦听协议状态演进:从基础写穿透 VI、写回式 MSI,到增加独占态 E 规避私有写总线事务(MESI),再到拥有态 O 推迟脏数据写回(MOESI)。
- 总线与性能权衡:分裂事务总线提升吞吐但引入复杂瞬态;伪共享(False Sharing)与锁竞争乒乓效应通过块对齐与 LR/SC 预约机制缓解。
一、多核与可扩展性
- 自 2005 年起,系统性能提升主要来自每芯片核数增加(技术缩放 + ILP 受限);
- 多核性能的限制因素:应用并行度有限、访存与核间通信、编程复杂度。
Amdahl 定律
其中 是被加速部分占比, 是该部分的加速倍数。
推论:让常见情况快(make the common case fast)。 例:90% 可并行、10% 串行,则 。要用好 1000 核,需要极高的 。
二、通信模型
| 模型 | 地址空间 | 通信方式 | 低层编程模型 |
|---|---|---|---|
| 共享内存(Shared Memory) | 单一地址空间 | 隐式:读写内存(数据 + 控制如信号量/锁/屏障) | 线程 |
| 消息传递(Message Passing) | 各自独立地址空间 | 显式:send/recv 消息 | 进程 + 进程间通信(如 MPI) |
三、一致性 vs 一致(Coherence vs Consistency)
共享内存系统为性能设多个私有缓存,需提供"单一共享内存"的假象。直觉:读应返回最近写入的值——但"最近"如何定义?
- 一致性(Coherence):读能返回哪些值?——关注单个内存位置的读写;
- 一致(Consistency):写何时对读可见?——关注多个内存位置的读写。
一致性协议的两条规则
- 写传播(Write propagation):写最终对所有处理器可见;
- 写串行化(Write serialization):对同一位置的写被串行化(所有处理器看到相同顺序)。
保证写传播的方式:
- 写失效(Write-invalidate):写之前作废其他所有缓存副本;
- 写更新(Write-update):写之后更新其他所有缓存副本。
跟踪共享状态并串行化请求的方式:
- 侦听式(Snooping-based):所有缓存通过共享总线观察彼此动作(总线是串行化点);
- 目录式(Directory-based):一致性目录跟踪私有缓存内容并串行化请求(目录是串行化点)。
四、侦听式一致性(Snooping)[Goodman, 1983]
各缓存控制器监听总线以保持各处理器的内存视图一致。总线提供串行化点(广播、全序)。每个核的缓存控制器侦听所有总线事务,响应来自核与总线的请求、改变所选缓存块状态、产生总线事务。协议用有限状态机(FSM)描述。
1. 简单协议:有效/无效(VI)
假设写穿透(writethrough)缓存。状态转换记法:触发动作 / 采取的动作。
- 动作:处理器读 PrRd、处理器写 PrWr、总线读 BusRd、总线写 BusWr;
- Valid:
PrRd/--、PrWr/BusWr、BusWr/--→Invalid; - Invalid:
PrRd/BusRd→Valid、PrWr/BusWr→Valid。
VI 的问题:每次写都更新主存,每次写都需广播 + 侦听。
2. 修改/共享/无效(MSI)
允许写回(writeback)缓存 + 本地满足写。
- 状态:M(Modified,已修改独占脏)、S(Shared,共享只读)、I(Invalid);
- 新动作:总线读独占 BusRdX、总线写回 BusWB;
- 关键转换:写时发
BusRdX获得独占进入 M;M 态被其他核 BusRd 时需BusWB写回降为 S;M 态被 BusRdX 时写回后作废。
MSI 相比 VI 的优势:核 0 进入 M 后,其后续的读和写都可本地满足,无需总线事务。
缓存干预(intervention):MSI 允许缓存不更新主存就服务写,故主存可能有陈旧数据。当另一核请求时,持有脏数据的缓存必须供数据并覆盖主存的响应。
3. MSI 优化:独占态 E → MESI
- 观察:对私有数据做读-改-写序列很常见,MSI 中读会进入 S,写还需一次 BusRdX;
- 方案:加 E 态(Exclusive,独占且干净)。若无其他共享者,读直接获得 E 而非 S;写则静默地 E→M(无需总线事务)。
MESI:M(已修改独占)、E(独占未修改)、S(共享)、I(无效),提升私有读写数据性能。
4. MSI 优化:拥有态 O → MOSI / MOESI
- 观察:M→S 转换必须写回;频繁读写共享时开销大,能否把写回推迟到 S 之后?
- 方案:加 O 态(Owner)= S + 写回责任。M→S 时,一个共享者(通常原持 M 者)保留为 O 而非 S;逐出时由 O 写回(或另一共享者 S→O)。
经验:私有读写 ≫ 共享只读时常用 E;写回昂贵(主存 vs L3)时才用 O。
五、总线与非原子性
分裂事务与流水总线
- 原子事务总线:简单但吞吐低;
- 分裂事务总线(Split-Transaction):支持多个并发事务(吞吐高),响应可能乱序到达,常实现为多条总线(请求 + 响应)。
非原子性 → 瞬态(Transient)状态
协议须处理缺乏原子性的情况,状态分两类:
- 稳定态(如 MSI);
- 瞬态(如 I→S、I→M、S→M):因分裂 + 竞争而出现,更复杂。
扩展一致性的难题
可实现比总线扩展性更好的有序互连,但广播本质上不可扩展(数百次缓存侦听的带宽与能量)。
例:Starfire E10000 —— 一致性请求单播到根处串行化,再广播下发到所有处理器。 出路:目录式一致性——所有事务经目录路由,跟踪私有缓存内容(无广播),作为冲突请求的排序点(支持无序网络)。
六、一致性带来的性能问题
问题 1:伪共享(False Sharing)
一个缓存块含多个字,一致性在块级而非字级进行。若 P1 写 、P2 写 且二者同块,该块会因地址同块而被反复不必要地作废(ping-pong)。
问题 2:同步
一致性协议会让 mutex 在各核私有缓存间反复乒乓(Ping-Pong)。可用 test&test&set(先非原子读 mutex,仅当为 0 才执行 swap)减少 ping-pong。
问题 3:总线占用
- 原子读-改-写指令一般需两次内存(总线)操作且中间不能插入其他处理器的内存操作;
- 多处理器下须在整个原子读写期间锁总线 → 对简单总线昂贵、对分裂事务总线极昂贵;
- 现代处理器改用 load-reserve / store-conditional。
Load-reserve & Store-conditional
用特殊寄存器保存预约标志、地址与 store-conditional 的结果:
Load-reserve R, (a): Store-conditional (a), R:
<flag, adr> ← <1, a> if <flag, adr> == <1, a>
R ← M[a] then 取消其他处理器对 a 的预约;
M[a] ← R; status ← succeed
else status ← fail
侦听器若看到对预约寄存器地址的 store 事务,就把预约位清 0。多个处理器可同时预约 a;这对总线流量而言就像普通 load/store。 性能:内存事务总数不必然减少,但拆分原子指令可提高总线利用率(尤其分裂事务总线)、减少缓存乒乓效应(尝试获锁的处理器不必每次都 store)。
侦听式缓存一致性与同步机制总结
- 多核性能受 Amdahl 定律与通信约束;共享内存系统需一致性协议维持"单一内存"假象;
- 一致性管单地址读写、一致管多地址可见时序;写传播靠失效/更新,串行化靠侦听/目录;
- 侦听式协议从 VI → MSI → MESI(加 E 省私有读写)→ MOESI(加 O 推迟写回)逐步优化;
- 广播不可扩展 → 引出目录式;伪共享、同步 ping-pong、总线占用是三大性能问题,load-reserve/store-conditional 是现代原子操作方案。
许多工程师容易混淆 Coherence 与 Consistency,两者的正交性是多核架构体系的基石:
- 一致性(Coherence) 是微架构层面的契约,作用域严格限定在「单个内存地址」上。它要求所有处理器对同一物理地址的写入看到完全一致的全局全序(写串行化),并在有限时间内感知到更新(写传播),防止读取陈旧脏数据。MESI 状态机、总线侦听或目录协议,全部在捍卫这一单地址契约。
- 内存一致性模型(Consistency) 则是体系结构/ISA 层面的契约,作用域涵盖「不同内存地址」之间的读写时序。当核 1 写入数据地址 A 后再写入标志位地址 B,核 2 在看到 B 更新时,是否能保证一定读到 A 的最新值?这取决于内存模型是顺序一致性(SC)、全存储定序(TSO)还是弱内存序(Weak Ordering)。即使底层 MESI 协议运行得完美无瑕,若微架构允许写缓冲(Store Buffer)乱序旁路或编译器重排了访存指令,依然会违反多地址间的直觉顺序。因此,Coherence 解决单变量数据的真伪,而 Consistency 规范多变量交互的契约。 :::
下一讲:目录式缓存一致性