MESI
Table of Contents
1. MESI
https://en.wikipedia.org/wiki/MESI_protocol
https://www.scss.tcd.ie/Jeremy.Jones/vivio/caches/MESIHelp.htm
1.1. MESI
MESI (Modified, Exclusive, Shared, Invalid) 是一个 cache 一致性协议, 它能保存各个 cpu 的 cache 是一致的. 若 SMP 使用原始的 MESI, 可以保证各个 cpu 不需其它措施就能读到最新的值.
每个 cpu 的 cache line 保存着它当前的状态 (M, E, S, I), 本 cpu 的读写会导致本cpu cache 状态变化, 同时通过 MESI bus 消息可以影响其它 cpu 的 cache 状态.
cpu_a/cpu_b 两个 cpu 读写同一个地址, 其状态 sa/sb 的变化:
sa | sb | 备注 | |
---|---|---|---|
初始 | I | I | |
cpu_a read | E | I | |
cpu_b read | S | S | |
cpu_a read | - | - | |
cpu_a write | M | I | cpu_a write 只写 cache_a, 不 flush |
cpu_a read/write | - | - | |
cpu_b read | S | S | cpu_b read 导致 cache_a flush |
cpu_a read | - | - | |
cpu_a write | M | I | |
cpu_b write | S | S | 相当于 cpu_b read (MI->SS) + |
I | M | cpu_b write (SS->IM), 所以 cache_a 会 flush |
可见:
- E/M 表示独占, 读写都不需要考虑别人
- S 表示共享, 读不需要考虑别人, 写时需要升级成独占
- I 表示不可用, 读写都需要考虑别人, 因为本地数据已经被 invalidate
- M 状态用来推迟写内存, 且能合并多次写操作, 只有 M->S 时才需要写内存.
由于 E/I 状态的存在, a 的写操作不会直接写到内存(并同步到 b 的 cache), 直到 b 有读操作/写操作
1.2. store buffer
https://en.wikipedia.org/wiki/MESI_protocol#Store_Buffer
当 cpu_a 要写 cache 时, 它需要先 invalidate 其它 cpu, 收到所有 cpu 的 ack 后再写数据到 cache. 为了避免等待其它 cpu 的 ack, 会将数据暂存在它的 store buffer
1.3. invalidate queue
https://en.wikipedia.org/wiki/MESI_protocol#Invalidate_Queues
其它 cpu 收到 cpu_a 的 invalidate 请求后, 会直接返回 ack, 然后把请求放在 invalidate queue 慢慢处理.
1.4. barrier
由于 store buffer 的存在, 需要一个 write barrier 显式的处理 store buffer.
由于 invalidate queue 的存在, 需要一个 read barrier 显式的处理 invalidate queue.
这两个 barrier 通常需要配合使用:
- write barrier 保证修改已经写入 cache
- read barrier 保证当前 cpu 处理完所有的 invalidate 请求, 相应 cache 转换为 I 状态
所以 barrier 并不意味着 `刷新内存`, 它只是用来确保 cache 状态是最新的, 至于怎么能读到最新的内存由 MESI 保证.