深刻浅出计算机组成原理学习笔记:第三十九讲

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

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

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

 

一、先把数据写入到L2 Cache里面,而后把Cache Block标记成脏的。这个时候,数据其实并无被同步到L3 Cache或者主内存里多线程

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

三、若是咱们的CPU只有1号核心这一个CPU核,那这实际上是没有问题的。不过,咱们旁边还有一个2号核心呢!性能

四、这个时候,2号核心尝试从内存里面去读取iPhone的价格,结果读到的是一个错误的价格。这是由于,iPhone的价格刚刚被1号核心更新过。
可是这个更新的信息,只出如今1号核心的L2 Cache里,而没有出如今2号核心的L2 Cache或者主内存里面。spa

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

2、写传播

为了解决这个缓存不一致的问题,咱们就须要有一种机制,来同步两个不一样核内心面的缓存数据。那这样的机制须要知足什么条件呢?我以为可以作到下面两点就是合理的。3d

第一点叫 写传播(Write Propagation)。写传播是说,在一个CPU核内心,咱们的Cache数据更新,必须可以传播到其余的对应节点的Cache Line里。blog

既然咱们数据写完了,天然要同步到其余CPU核的Cache里事件

3、事务的串行化

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

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

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

 


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

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

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

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

一、是一个CPU核心对于数据的操做,须要同步通讯给到其余CPU核心。
二、若是两个CPU核内心有同一个数据的Cache,那么对于这个Cache数据的更新,须要有一个“锁”的概念。只有拿到了对应Cache Block的“锁”以后,才能进行对应的数据更新。

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

4、总线嗅探

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

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

总线自己就是一个特别适合广播进行数据传输的机制,因此总线嗅探这个办法也是咱们平常使用的IntelCPU进行缓存一致性处理的解决方案。
关于总线这个知识点,咱们会放在后面的I/O部分更深刻地进行讲解,这里你只须要了解就能够了。

5、写失效协议

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

 

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

一、只有一个CPU核心负责写入数据,
二、其余的核心,只是同步读取到这个写入。在这个CPU核心写入Cache以后,它会去广播一个“失效”请求告诉全部其余的CPU核心。
三、其余的CPU核心,只是去判断本身是否也有一个“失效”版本的CacheBlock,而后把这个也标记成失效的就行了。

6、写广播协议

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

 


一、一个写入请求广播到全部的CPU核心,同时更新各个核内心的Cache。写广播在实现上天然很简单,
二、可是写广播须要占用更多的总线带宽。
  写失效只须要告诉其余的CPU核心,哪个内存地址的缓存失效了,
  可是写广播还须要把对应的数据传输给其余CPU核心

7、Cache Line的四个不一样的标记

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

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

“已修改”和“已失效”

一、这两个状态比较容易理解。所谓的“已修改”,就是咱们上一讲所说的“脏”的Cache Block。Cache Block里面的内容咱们已经更新过了,
可是尚未写回到主内存里面。
二、而所谓的“已失效“,天然是这个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的内容,仔细研读一下。

8、总结延伸

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

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

以后,我介绍了基于总线嗅探机制的MESI协议。MESI协议是一种基于写失效的缓存一致性协议。写失效的协议的好处是,咱们不须要在总线上传输数据内容,
而只须要传输操做信号和地址信号就行了,不会那么占总线带宽。MESI协议,是已修改、独占、共享以及已失效这四个缩写的合称。独占和共享状态,就好像咱们在多线程应用开发里面的读写锁机制,确保了咱们的缓存一致性。而整个MESI的状态变动,则是根据来自本身CPU核心的请求,以及来自其余CPU核心经过总线传输过来的操做信号和地址信息,进行状态流转的一个有限状态机。

相关文章
相关标签/搜索