cache 一致性解密

实际上,CPU Cache 里的最小存储单元就是 Cache Line,Intel CPU的一个 Cache Line 存储 64 个字节,每一级 Cache 都被划分为很多组 Cache Line,典型的情况是4 条 Cache Line 为一组,当 Cache 从 Memory 中加载数据时,一次加载一条 Cache Line 的数据。下图给出了 Cache 的结构。

在这里插入图片描述

每个 Cache Line 的头部有两个 Bit 来表示自身的状态,总共有 4 种状态。

  • M(Modified):修改状态,其他 CPU 上没有数据的副本,并且在本 CPU 上被修改过,
    与存储器中的数据不一致,最终必然会引发系统总线的写指令,将 Cache Line 中的数
    据写回到 Memory 中。
  • E(Exclusive):独占状态,表示当前 Cache Line 中包含的数据与 Memory 中的数据一
    致,此外,其他 CPU 上没有数据的副本。
  • S(Shared):共享状态,表示 Cache Line 中包含的数据与 Memory 中的数据一致,而且
    在当前 CPU 和至少在其他某个 CPU 中有副本。
  • I(Invalid):无效状态,当前 Cache Line 中没有有效数据或者该 Cache Line 数据已经失
    效,不能再用,当 Cache 要加载新数据时,优先选择此状态的 Cache Line,此外,Cache
    Line 的初始状态也是 I 状态。
状态cacheline 数据是否有效其他cpu核 中是否有副本cache 数据是否被正在被修改cache 数据是否与Memory 中的数据一致
M(Modified)101不定,大概率是一致的
E(Exclusive)1001
S(Shared)1101
I(Invalid)0不定不定不定

MESI 协议是用 Cache Line 的上述 4 种状态命名的,对 Cache 的读写z操作引发了 Cache Line的状态变化,因而可以理解为一种状态机模型。但 MESI 的复杂和独特之处在于状态有两种视角:一种是当前读写操作(Local Read/Write)所在 CPU 看到的自身的 Cache Line 状态及其他CPU 上对应的 Cache Line 状态;另一种是一个 CPU 上的 Cache Line 状态的变迁会导致其他 CPU上对应的 Cache Line 的状态变迁。如下所示为 MESI 协议的状态图

在这里插入图片描述

  • (1)结合这个状态图,我们深入分析 MESI 协议的一些实现细节。 ##### (1)某个 CPU(CPU A)发起本地读请求(Local Read),比如读取某个内存地址的变量,如果此时所有 CPU 的 Cache 中都没加载此内存地址,即此内存地址对应的 Cache Line 为无效状态(Invalid),则 CPU A 中的 Cache 会发起一个到 Memory 的内存 Load 指令,在相应的 Cache Line中完成内存加载后,此 Cache Line 的状态会被标记为 Exclusive。接下来,如果其他 CPU(CPU B)在总线上也发起对同一个内存地址的读请求,则这个读请求会被 CPU A 嗅探到(SNOOP),然后 CPU A 在内存总线上复制一份 Cache Line 作为应答,并将自身的 Cache Line 状态改为Shared,同时 CPU B 收到来自总线的应答并保存到自己的 Cache 里,也修改对应的 Cache Line状态为 Shared。

  • (2)某个 CPU(CPU A)发起本地写请求(Local Write),比如对某个内存地址的变量赋值,如果此时所有 CPU 的 Cache 中都没加载此内存地址,即此内存地址对应的 Cache Line 为无效状态(Invalid),则 CPU A 中的 Cache Line 保存了最新的内存变量值后,其状态被修改为 Modified。随后,如果 CPU B 发起对同一个变量的读操作(Remote Read),则 CPU A 在总线上嗅探到这个读请求以后,先将 Cache Line 里修改过的数据回写(Write Back)到 Memory 中,然后在内存总线上复制一份 Cache Line 作为应答,最后将自身的 Cache Line 状态修改为 Shared,由此产生的结果是 CPU A 与 CPU B 里对应的 Cache Line 状态都为 Shared。

  • (3)以上面第 2 条内容为基础,CPU A 发起本地写请求并导致自身的 Cache Line 状态变为Modified,如果此时 CPU B 发起同一个内存地址的写请求(Remote Write),则我们看到状态图里此时 CPU A 的 Cache Line 状态为 Invalid,其原因如下。CPU B 此时发出的是一个特殊的请求——读并且打算修改数据,当 CPU A 从总线上嗅探到这个请求后,会先阻止此请求并取得总线的控制权(Takes Control of Bus),随后将 Cache Line里修改过的数据回写道 Memory 中,再将此 Cache Line 的状态修改为 Invalid(这是因为其他CPU 要改数据,所以没必要改为 Shared)。与此同时,CPU B 发现之前的请求并没有得到响应,于是重新发起一次请求,此时由于所有 CPU 的 Cache 里都没有内存副本了,所以 CPU B的 Cache 就从 Memory 中加载最新的数据到 Cache Line 中,随后修改数据,然后改变 Cache Line的状态为 Modified。

  • (4)如果内存中的某个变量被多个 CPU 加载到各自的 Cache 中,从而使得变量对应的 Cache Line 状态为 Shared,若此时某个 CPU 打算对此变量进行写操作,则会导致所有拥有此变量缓存的 CPU 的 Cache Line 状态都变为 Invalid,这是引发性能下降的一种典型 Cache Miss 问题

当前状态CPU(A) 发起本请求类别下一个状态CPU(B) 发起本请求类别再下一个状态备注
InvalidRead -->>Exclusiveread -->>Shared
InvalidWrite -->>Modifiedread -->>Shared
InvalidWrite -->>ModifiedWrite -->>Invalid(原因是不能同时写,要加锁,和数据库一样)CPU B 发现之前的请求并没有得到响应,于是重新发起一次请求
SharedWrite -->>Invalid引发性能下降的一种典型 Cache Miss 问题
架构解密电子书下载

链接:https://pan.baidu.com/s/1FEoLtB2gxL2JXcMnTmbyZQ?pwd=hiy4
提取码:hiy4

posted @ 2022-08-19 22:43  luoganttcc  阅读(10)  评论(0编辑  收藏  举报