CXL.cache 目录协议的四大基本状态
做 CXL 协议的这些年,我见过不少工程师一上来就盯着几十页的状态转换表,看得头皮发麻。其实不用慌,先摸清四个基本状态,剩下的事情就是组合拳。今天咱们就把 Invalid、Shared、Exclusive、Modified 这四个状态的定义和气质聊透。
1. INVALID (I) – 啥也没有
Invalid,简写 I,字面意思就是无效。当前缓存行在本地 cache 里不存在,或者数据已经过时。说白了,你去查这一行,本地找不到任何副本,必须走目录去请求。
我个人习惯把 I 状态叫“空位”。刚开始做项目时容易混淆:I 状态不等于“没分配”,它只是一个标记,告诉 cache 不要用这行数据。如果目录收到对这行的访问,而请求者状态是 I,那就正常发起填充。
2. SHARED (S) – 大家一起读
Shared,简写 S,表示当前缓存行是干净的(clean),并且与目录或者其他 cache 保持一致性。多个 agent 可以同时拥有同一行的 S 副本,大家都能读,但谁都不能写。
想象一下会议室里的一份打印文档,所有人手里拿的都是影印件,原件放在前台。只要不拿笔划,大家都能看。这就是 S 状态。
仔细想:S 状态的 cache 行可以 直接返回给其他请求者,不需要去目录抢行。但要注意,一旦有人想写,目录就必须把其他 S 副本全部作废。我在联调时遇到过一个问题:agent 持有 S 状态后,收到写请求,但它自己并没有主动发起 invalidate,导致数据不一致。嗯,协议规定必须由写者先拿到 Exclusive 或 Modified 权限,不能自己糊里糊涂去写。
3. EXCLUSIVE (E) – 独占访问权
Exclusive,简写 E,这个状态有点特殊。它表示当前 cache 持有数据的唯一副本(或者至少知道没有其他 S 副本),并且数据是干净的,跟主存一致。
你可以把 E 理解成“准写入状态”。持有 E 的 agent 能读,也能写,但写之前不需要发 invalidate,因为其他 agent 都没副本。但是!写完之后状态就必须变为 Modified,数据不再干净。
为什么需要 E 状态?我早年看协议文档时也纳闷:为什么不直接用 M 状态?E 状态的作用是 优化写场景。如果一个 agent 拿到了 E,接下来要写,直接变成 M 就行,不用额外发 snoop,减少延迟和带宽。想想看,如果直接拿 M,目录还得先确认所有人都在 I 状态,浪费一个来回。
4. MODIFIED (M) – 脏数据,唯我独尊
Modified,简写 M,这是最“霸道”的状态。当前 cache 持有唯一副本,而且数据已经被修改过,与主存不一致。任何其他 agent 想读或者写这一行,都必须先问 M 的持有者把数据吐出来。
M 状态的 cache 行,在协议中被视为“owner”。它可以直接响应远程的读请求,把脏数据交给请求者,并同时更新主存(或者让对方写回)。具体流程要看协议变种,但核心不变:别的 agent 问数据,M 的持有者不能装死。
我在一个多 chiplet 项目中遇到过一个性能坑:某个 agent 长期持有 M 状态,另一个 agent 做 streaming read 时总是被 pending 住。后来发现是 M 持有者处理 snoop 的优先级太低,导致整个流水线卡住。解决方案是给 M 状态的 snoop 响应设最高优先级。
| 状态 | 数据有效 | 数据干净 | 是否唯一副本 | 可写? | 需通知目录? |
|---|---|---|---|---|---|
| I | 否 | – | – | 不可写 | 否 |
| S | 是 | 是 | 否(可能有多个) | 不可直接写 | 是(写前需升级) |
| E | 是 | 是 | 是 | 可直接写 | 写后需变为 M |
| M | 是 | 否 | 是 | 可直接写 | 是(写时已通知) |
状态转换的核心原则
四个状态之间的转换不是随意的,有两条铁律:
- 数据一致性不能丢:从 I 到 S/E/M 必须通过目录获得最新数据;从 E/M 回到 I 必须确保别人没有依赖。
- S 和 E 不能同时存在:同一个目录行,要么全是 S,要么只有一个 E 或 M。不能同时有人声称 E 又有人声称 S – 如果出现这种情况,恭喜你,协议 bug。
下面这张图把四个状态的定位和主要转换方向画出来了。注意这只是核心骨架,完整的迁移图咱们后面章节再展开。
– Invalid 是起点,也是终点(evict 后回 I)。
– Shared 表示多人可读,但要写必须升级。“多个 S 可以共存”是协议的正确性基础。
– Exclusive 是一个“干净但独占”的过渡状态,用来加速写操作。
– Modified 是唯一允许脏数据的状态,也是 cache 一致性协议中最需要小心处理的状态。
我一直觉得,这四种状态就像四张扑克牌,不同的排列组合就能支撑起整个 CXL.cache 协议的一致性模型。你只要把每个状态的“权利”和“义务”记住,后面的状态转换规则自然能推导出来。多说一句,千万别死记硬背,多想想“如果我是目录,我怎么知道别人有没有 S 副本?”——想通了,状态机就活了。