什么叫通俗易懂?用动图的方式,理解CPU缓存一致性协议

本文通过一个在线网站详细介绍了MESI协议的四种状态——Modified、Exclusive、Shared、Invalidated,以及它们之间的转换过程。通过实际操作,读者可以理解CPU缓存一致性如何在多核环境中保持,并通过动画效果直观感受状态变化。此外,文章提供了一个MESI状态转换的表格,帮助读者更好地掌握协议原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

大家好,我是小林。

我之前写过 CPU 缓存一致性 MESI 协议:10 张图打开 CPU 缓存一致性的大门。

然后期间挺多人对 MESI 协议的转换有疑问,其实我在文章中把 MESI 协议状态切换的各个过程都总结成了一个表格,可能内容太多,很多小伙伴没有仔细看。

就在昨天,我发现个可以「在线体验 MESI 协议状态转换」过程的网站,地址如下:

https://www.scss.tcd.ie/Jeremy.Jones/VivioJS/caches/MESIHelp.htm

舒服了!用动图的方式,理解CPU缓存一致性协议


我先给大家复习下 MESI 协议,然后再跟大家讲一些这个网站怎么用。

MESI 协议

MESI 协议其实是 4 个状态单词的开头字母缩写,分别是:

  • Modified,已修改
  • Exclusive,独占
  • Shared,共享
  • Invalidated,已失效

这四个状态来标记 Cache Line 四个不同的状态。

「已修改」状态就是我们前面提到的脏标记,代表该 Cache Block 上的数据已经被更新过,但是还没有写到内存里。而「已失效」状态,表示的是这个 Cache Block 里的数据已经失效了,不可以读取该状态的数据。

「独占」和「共享」状态都代表 Cache Block 里的数据是干净的,也就是说,这个时候 Cache Block 里的数据和内存里面的数据是一致性的。

「独占」和「共享」的差别在于,独占状态的时候,数据只存储在一个 CPU 核心的 Cache 里,而其他 CPU 核心的 Cache 没有该数据。这个时候,如果要向独占的 Cache 写数据,就可以直接自由地写入,而不需要通知其他 CPU 核心,因为只有你这有这个数据,就不存在缓存一致性的问题了,于是就可以随便操作该数据。

另外,在「独占」状态下的数据,如果有其他核心从内存读取了相同的数据到各自的 Cache ,那么这个时候,独占状态下的数据就会变成共享状态。

那么,「共享」状态代表着相同的数据在多个 CPU 核心的 Cache 里都有,所以当我们要更新 Cache 里面的数据的时候,不能直接修改,而是要先向所有的其他 CPU 核心广播一个请求,要求先把其他核心的 Cache 中对应的 Cache Line 标记为「无效」状态,然后再更新当前 Cache 里面的数据。

事实上,整个 MESI 的状态可以用一个有限状态机来表示它的状态流转。还有一点,对于不同状态触发的事件操作,可能是来自本地 CPU 核心发出的广播事件,也可以是来自其他 CPU 核心通过总线发出的广播事件。下图即是 MESI 协议的状态图:

舒服了!用动图的方式,理解CPU缓存一致性协议

MESI 协议的四种状态之间的流转过程,我汇总成了下面的表格,你可以更详细的看到每个状态转换的原因:

舒服了!用动图的方式,理解CPU缓存一致性协议

网站体验

接下来说说,怎么玩这个网站。

舒服了!用动图的方式,理解CPU缓存一致性协议

看上图,共分为三个部分:

  • 第一部分,内存。显示内存地址和数据;
  • 第二部分,CPU 缓存。显示 CPU 缓存的变量数据和 MESI 协议状态,因为我现在还没开始操作,所以显示的是空白。
  • 第三部分,CPU 操作。共有三个 CPU,每个 CPU 都有各自的 Cache,CPU 操作分别「读」和「写」,这部分是我们手动操作的部分。

而且 CPU 和内存之间有三条总线,分别是:

  • 数据总线(Data Bus):在CPU与内存之间来回传送需要处理或是需要储存的数据。
  • 地址总线(Adress Bus),用来指定在内存之中储存的数据的地址。
  • shared,这个我也不知道是什么总线,网上没搜到资料,网站上最细那条总线就是这个名字,作用是控制 Cache 的数据状态。

接下来,来演示下效果。

我操作 CPU1 读取 a0 变量,此时页面会显示如下(实际上是有动画的效果的,我这里就不录制动图了,建议大家自己去操作一遍,自己感受下过程):

舒服了!用动图的方式,理解CPU缓存一致性协议

可以看到,CPU1 核心从内存读取了 a0 变量的数据,并缓存在了 Cache1 里,而且此时状态为 E (独占)。

然后我操作 CPU2 读取 a0 变量,此时页面会显示如下:

舒服了!用动图的方式,理解CPU缓存一致性协议

可以看到,CPU1 和 CPU1 的 Cache 数据的状态都是 S(共享),和表格中表述的现象一致。

舒服了!用动图的方式,理解CPU缓存一致性协议

别看我的结果是静态的,实际上当我操作完 CPU2 读取 a0 变量后,实际上是有动画效果的,这里有个小技巧,在动画的过程中,我们可以点击网站任意一个位置,就会暂停,然后再点击就开始,这样我们可以很清晰的知道这个状态过程是怎么通过这三个总线完成的。

我大概简述下过程:

  1. 点击 CPU2 的 read a0 操作;
  2. CPU2 会向地址总线,发送读取 a0 变量的数据的请求,此时该请求不仅会被内存收到,也会被其他 CPU 核心收到。
  3. CPU1 从地址总线得知,CPU2 发起的读取地址存在于 CPU1 Cache 里,于是 CPU1 Cache 里数据的状态会从 E(独占)变更为 S(共享);
  4. 内存收到 CPU2 发起的读取 a0 数据的请求后,就会通过数据总线将数据传递给 CPU2;
  5. 最后数据会写到 CPU2 Cache 里,且状态是 S(共享)。

其他状态的变更,我在这里就不介绍了,大家自己去网站体验下,这样会感触比较深,光听我讲也记不住。

可以对照我文章中 MESI 状态转换的表格来做实验,感受下 MESI 状态到底是如何在不用加锁的情况下,是如何实现 CPU 缓存一致性的。

网站地址:
https://www.scss.tcd.ie/Jeremy.Jones/VivioJS/caches/MESIHelp.htm

原文链接:
https://mp.weixin.qq.com/s/otJfvn1M3ObNqonrkFTiYg

作者:小林coding

如果觉得本文对你有帮助,可以转发关注支持一下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值