深入浅出计算机组成原理学习笔记:MESI协议-如何让多核CPU的高速缓存保持一致?(第39讲)..._weixin_30691871的博客-程序员秘密

一、缓存一致性问题指的是什么

在这两个CPU核心里,1号核心要写一个数据到内存里。这个怎么理解呢?我拿一个例子来给你解释。

比方说,iPhone降价了,我们要把iPhone最新的价格更新到内存里。为了性能问题,它采用了上一讲我们说的写回策略,

 

1、先把数据写入到L2 Cache里面,然后把Cache Block标记成脏的。这个时候,数据其实并没有被同步到L3 Cache或者主内存里

2、1号核心希望在这个Cache Block要被交换出去的时候,数据才写入到主内存里。

3、如果我们的CPU只有1号核心这一个CPU核,那这其实是没有问题的。不过,我们旁边还有一个2号核心呢!

4、这个时候,2号核心尝试从内存里面去读取iPhone的价格,结果读到的是一个错误的价格。这是因为,iPhone的价格刚刚被1号核心更新过。
但是这个更新的信息,只出现在1号核心的L2 Cache里,而没有出现在2号核心的L2 Cache或者主内存里面。

这个问题,就是所谓的缓存一致性问题,1号核心和2号核心的缓存,在这个时候是不一致的。

二、写传播

为了解决这个缓存不一致的问题,我们就需要有一种机制,来同步两个不同核心里面的缓存数据。那这样的机制需要满足什么条件呢?我觉得能够做到下面两点就是合理的。

第一点叫 写传播(Write Propagation)。写传播是说,在一个CPU核心里,我们的Cache数据更新,必须能够传播到其他的对应节点的Cache Line里。

既然我们数据写完了,自然要同步到其他CPU核的Cache里

三、事务的串行化

第二点叫 事务的串行化(Transaction Serialization),事务串行化是说,我们在一个CPU核心里面的读取和写入,在其他的节点看起来,顺序是一样的。

我们还拿刚才修改iPhone的价格来解释。这一次,我们找一个有4个核心的CPU。1号核心呢,先把iPhone的价格改成了5000块。差不多在同一个时间,2号核心把iPhone的价格改成了

这里两个修改,都会传播到3号核心和4号核心差不多在同一个时间,2号核心把iPhone的价格改成了6000块。

 


1、然而这里有个问题,3号核心先收到了2号核心的写传播,再收到1号核心的写传播。所以3号核心看到的iPhone价格是先变成了6000块,再变成了5000块。
2、而4号核心呢,是反过来的,先看到变成了5000块,再变成6000块。虽然写传播是做到了,但是各个Cache里面的数据,是不一致的。

事实上,我们需要的是,从1号到4号核心,都能看到相同顺序的数据变化。比如说,都是先变成了5000块,再变成了6000块。这样,我们才能称之为实现了事务的串行化。

事务的串行化,不仅仅是缓存一致性中所必须的。比如,我们平时所用到的系统当中,最需要保障事务串行的就是数据库。多个不同的连接去访问数据库的时候,
化我们必须保障事务的串行化,做不到事务的串行化的数据库,根本没法作为可靠的商业数据库来使用。

而在CPU Cache里做到事务串行化,需要做到两点:

1、是一个CPU核心对于数据的操作,需要同步通信给到其他CPU核心。
2、如果两个CPU核心里有同一个数据的Cache,那么对于这个Cache数据的更新,需要有一个“锁”的概念。只有拿到了对应Cache Block的“锁”之后,才能进行对应的数据更新。

接下来,我们就看看实现了这两个机制的MESI协议。

四、总线嗅探

要解决缓存一致性问题,首先要解决的是多个CPU核心之间的数据传播问题。最常见的一种解决方案呢,叫作 总线嗅探(Bus Snooping)。
这个名字听起来,你多半会很陌生,但是其实特很好理解。

这个策略,本质上就是把所有的读写请求都通过总线(Bus)广播给所有的CPU核心,然后让各个核心去“嗅探”这些请求,再根据本地的情况进行响应。

总线本身就是一个特别适合广播进行数据传输的机制,所以总线嗅探这个办法也是我们日常使用的IntelCPU进行缓存一致性处理的解决方案。
关于总线这个知识点,我们会放在后面的I/O部分更深入地进行讲解,这里你只需要了解就可以了。

五、写失效协议

基于总线嗅探机制,其实还可以分成很多种不同的缓存一致性协议。不过其中最常用的,就是今天我们要讲
的MESI协议。和很多现代的CPU技术一样,MESI协议也是在Pentium时代,被引入到Intel CPU中的。

 

MESI协议,是一种叫作 写失效(Write Invalidate)的协议。在写失效协议里:

1、只有一个CPU核心负责写入数据,
2、其他的核心,只是同步读取到这个写入。在这个CPU核心写入Cache之后,它会去广播一个“失效”请求告诉所有其他的CPU核心。
3、其他的CPU核心,只是去判断自己是否也有一个“失效”版本的CacheBlock,然后把这个也标记成失效的就好了。

六、写广播协议

相对于写失效协议,还有一种叫作 写广播(Write Broadcast)的协议。

 


1、一个写入请求广播到所有的CPU核心,同时更新各个核心里的Cache。写广播在实现上自然很简单,
2、但是写广播需要占用更多的总线带宽。
  写失效只需要告诉其他的CPU核心,哪一个内存地址的缓存失效了,
  但是写广播还需要把对应的数据传输给其他CPU核心

七、Cache Line的四个不同的标记

做不到事务串行话的数据库,根本没法作为可靠的商业书库看来使用

M:代表已修改(Modified)
E:代表独占(Exclusive)
S:代表共享(Shared)
I:代表已失效(Invalidated)

“已修改”和“已失效”

1、这两个状态比较容易理解。所谓的“已修改”,就是我们上一讲所说的“脏”的Cache Block。Cache Block里面的内容我们已经更新过了,
但是还没有写回到主内存里面。
2、而所谓的“已失效“,自然是这个Cache Block里面的数据已经失效了,我们不可以相信这个Cache Block里面的数据。

“独占”和“共享”这两个状态。

这就是MESI协议的精华所在了。无论是独占状态还是共享状态,缓存里面的数据都是“干净”的。这个“干净”,自然对应的是前面所说的“脏”的,也就是
说,这个时候,Cache Block里面的数据和主内存里面的数据是一致的。

“独占”和“共享”这两个状态的差别在哪里呢?

这个差别就在于,在独占状态下,对应的Cache Line只加载到了当前CPU核所拥有的Cache里。其他的CPU核,并没有加载对应的数据到自己的Cache里。这个
时候,如果要向独占的Cache Block写入数据,我们可以自由地写入数据,而不需要告知其他CPU核。

在独占状态下的数据

如果收到了一个来自于总线的读取对应缓存的请求,它就会变成共享状态。这个共享状态是因为,这个时候,另外一个CPU核心,也把对应的Cache Block,从内存里面加载到了自己的Cache里来。

而在共享状态下

因为同样的数据在多个CPU核心的Cache里都有。所以,当我们想要更新Cache里面的数据的时候,不能直接修改,而是要先向所有的其他CPU核心广播一个请求,要求先把其他CPU核心里面的Cache,都变成无效的状态,然后再更新当前Cache里面的数据。这个广播操作,一般叫作RFO(Request
For Ownership),也就是获取当前对应Cache Block数据的所有权。

有没有觉得这个操作有点儿像我们在多线程里面用到的读写锁。在共享状态下,大家都可以并行去读对应的数据。但是如果要写,我们就需要通过一个锁,获取当前写入位置的所有权。

整个MESI的状态,可以用一个有限状态机来表示它的状态流转。需要注意的是,对于不同状态触发的事件操作,可能来自于当前CPU核心,也可能来自总线里其他CPU核心广播出来的信号。我把对应的状态机流转

图放在了下面,你可以对照着Wikipedia里面MESI的内容,仔细研读一下。

八、总结延伸

好了,关于CPU Cache的内容,我们介绍到这里就结束了。我们来总结一下。这一节,我们其实就讲了两块儿内容,一个是缓存一致性,另一个是MESI协议。

想要实现缓存一致性,关键是要满足两点。第一个是写传播,也就是在一个CPU核心写入的内容,需要传播到其他CPU核心里。
更重要的是第二点,保障事务的串行化,才能保障我们的数据是真正一致的,我们的程序在各个不同的核心上运行的结果也是一致的。
这个特性不仅在CPU的缓存层面很重要,在数据库层面更加重要。

之后,我介绍了基于总线嗅探机制的MESI协议。MESI协议是一种基于写失效的缓存一致性协议。写失效的协议的好处是,我们不需要在总线上传输数据内容,
而只需要传输操作信号和地址信号就好了,不会那么占总线带宽。

MESI协议,是已修改、独占、共享以及已失效这四个缩写的合称。独占和共享状态,就好像我们在多线程应用开发里面的读写锁机制,确保了我们的缓存一致性。
而整个MESI的状态变更,则是根据来自自己CPU核心的请求,以及来自其他CPU核心通过总线传输过来的操作信号和地址信息,进行状态流转的一个有限状态机。

转载于:https://www.cnblogs.com/luoahong/p/11358997.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_30691871/article/details/100004896

智能推荐

深度学习100问-12:深度学习有哪些经典数据集?_louwill12的博客-程序员秘密

很多朋友在学习了神经网络和深度学习之后,早已迫不及待要开始动手实战了。第一个遇到的问题通常就是数据。作为个人学习和实验来说,很难获得像工业界那样较高质量的贴近实际应用的大量数据集,这时候一些公开数据集往往就成了大家通往AI路上的反复摩擦的对象。 深度学习(CV方向)的经典数据集包括MNIST手写数字数据集、Fashion MNIST数据集、CIFAR-10和CIFAR-100数据...

为什么软件开发周期总是预估的2~3倍?_boss_mu的博客-程序员秘密

我们引用个案例形象的解释一下来,让我们从旧金山出发,沿着西海岸徒步旅行,到洛杉矶的纽波特沙滩面基吧→→→出处简单的来说 所有事情不会像表面上那么简单比如说 这个程序很简单 我一天就能搞定好吧 刚开始写 电脑老死机 折腾了半个小时才弄好刚写一会儿,父亲大人来了个电话,咱得接起,听后指示吧,又费了点时间。突然觉得肚子里翻江倒海,必须去厕所飞翔。好嘛一上午过去了。下午下决心好好写程序,然后突然跳出来了N个bug。这样原来预估的时间就不够了。配图的意思就是原来看着挺简单,但是一放大还带小

改变Windows鼠标滚动方向_不白码的博客-程序员秘密_windows 鼠标滚动方向

修改Windows系统鼠标滚动的方向,需要以下3步:windows+R打开"运行",输入devmgmt.msc,再打开"设备管理器" 找到"鼠标和其他指针设备",右键选择"属性",留意选中的这串值 回到"运行",输入regedit,打开注册编辑器,找到"FilpFlopWheel",双击修改数值数据为"1"即可...

使用mybatis plus出现分页无效、自定义的sql查询报错问题_snowwithrain的博客-程序员秘密_mybatisplus分页查询无效

最近使用mybatis plus,出现几个小问题,在这里记录一下:1.自定义的sql查询方法无法正常执行的问题2022-01-13 20:58:22.582 ERROR 64652 --- [nio-8080-exec-1] c.c.s.w.s.a.AbstractRestExceptionHandler : handle [500] exception with error key[forbidden].org.apache.ibatis.binding.BindingException: Inv

开发中PG,PL,SE,PM都是什么意思_嵌入式小窝的博客-程序员秘密_程序员se是什么意思

项目最顶层是项目负责人,接下来项目会落实到pm(项目经理PM),项目经理将任务分成若干个子项目,每个项目由一个pl(项目组长)负责。在每个子项目中,由SE(系统工程师)带领pg(程序员)共同完成。其中,PM和PL一般为具有资深项目管理经验、长期开发实践和良好交流能力的高级技术人才。SE需要具有独立的设计和提案能力,具有长期开发实践经验和交流能力。一般又可分为三种类型:第

必备的20个电路分析_十月拾岸的博客-程序员秘密_电路分析

初级层次:是熟练记住这二十个电路,清楚这二十个电路的作用。只要是电子爱好者,只要是学习自动化、电子等电控类专业的人士都应该且能够记住这二十个基本模拟电路。   中级层次:是能分析这二十个电路中的关键元器件的作用,每个元器件出现故障时电路的功能受到什么影响,测量时参数的变化规律,掌握对故障元器件的处理方法;定性分析电路信号的流向,相位变化;定性分析信号波形的变化过程;定性了解电路输入输出阻抗的大

随便推点

关于监听微服务功能_T5233的博客-程序员秘密

需求:在运营平台上弄一个监听各个微服务是否正常运行的预警功能做法:监听心跳做法1:在运营平台上设立一个static 的map,key为各个监听平台的名称,value为存入的时间2:在各个需监听的微服务中每个一分钟请求运营平台,向map中存入自己的名称+时间3:在运营平台中对比现在时间和存入的时间,若大于设定的请求超时需发送短信的链接则发送短信4:在map中,...

from TD3 to SAC_Enoch Liu98的博客-程序员秘密

TD3DDPG常常会遇到Q值overestimate的问题,这将会导致Critic部分给出错误的评判,导致Actor部分错误利用了这部分知识进行学习。TD3则是为了解决这个问题。技巧一:快速双q学习。TD3学习两个q函数而不是一个q函数(即twin),并使用两个q值中较小的一个作为Bellman误差损失函数中的目标。技巧二:延迟的政策更新。TD3更新策略(和目标网络)的频率低于q函数。本文建议每两个q函数更新一次策略更新。这样可以有效避免policy带来的偏差问题。技巧三:目标政策平滑。TD3为目

利用Sharding-Jdbc实现分表(亲测成功)_weixin_41704829的博客-程序员秘密

利用Sharding-Jdbc实现分表闲来无事,喜欢研究一些自己未接触过的技术~看到了当当开源的Sharding-JDBC组件,它可以在几乎不修改代码的情况下完成分库分表的实现。摘抄其中一段介绍: Sharding-JDBC直接封装JDBC API,可以理解为增强版的JDBC驱动,旧代码迁移成本几乎为零:可适用于任何基于java的ORM框架,如:JPA, Hibernate, Myba...

linux ICONV字符GB2312转换UTF8_天经地义之经的博客-程序员秘密

http://blog.chinaunix.net/uid-25135004-id-2782730.html指令:  #iconv -f GB2312 -t UTF-8 gb1.txt >gb2.txt           将gb1里的编码从GB2312转化成UTF-8  并重定向到gb2.txt  除了iconv命令,我们在linux系统下的man page的第三节还

吴恩达深度学习学习笔记——C2W3——超参数调试、Batch正则化和程序框架——作业——Tensorflow入门及使用Tensorflow构建第一个神经网络_预见未来to50的博客-程序员秘密

这里主要梳理一下作业的主要内容和思路,完整作业文件可参考:https://github.com/pandenghuang/Andrew-Ng-Deep-Learning-notes/tree/master/assignments/C2W3作业完整截图,参考本文结尾:作业完整截图。TensorFlow Tutorial (Tensorflow教程)Welcome to this week's programming assignment. Until now, you've always.