计算机操作系统学习笔记(3)——CPU缓存一致性

简介: 计算机操作系统学习笔记(3)——CPU缓存一致性

一、CPU Cache写回内存

之前说的CPU Cache缓存块实际分为:头标志Tag和数据块Data Block

前面说的直接映射,取模运算有可能发生冲突,发生了冲突就用Tag去标记。组标记(Tag)。这个组标记会记录当前 CPU Line 中存储的数据对应的内存块,我们可以⽤这个组标记来区分不同的内存块。

Cache里的数据总要写回内存的,那在什么时机才把 Cache 中的数据写回到内存呢?

这里有2种方案:写直达和写回
写直达:写直达法很直观,也很简单,把数据同时写⼊内存和 Cache 中,⽆论数据在不在 Cache ⾥⾯,每次写操作都会写回到内存,这样写操作将会花费⼤量的时间,⽆疑性能会受到很⼤的影响。
写回:在写回机制中,如果当发⽣写操作时,数据所对应的 Cache Block ⾥存放的是「别的内存地址的数据」的话,就要检查这个 Cache Block ⾥的数据有没有被标记为脏的,如果是脏的话,我们就要把这个 
Cache Block ⾥的数据写回到内存,然后再把当前要写⼊的数据,写⼊到这个 Cache Block ⾥,同时也把它标记为脏的;。这样的好处是,如果我们⼤量的操作都能够命中缓存,那么⼤部分时间⾥ CPU 都不需要读写
内存,⾃然性能相⽐写直达会⾼很多。
脏说明这个数据被更新了,说白了写回策略其实就是操作一个变量,直到换成了操作其他变量才更新

二、何为CPU缓存一致性问题?

举个例子:如果一个CPU有2个核心A和B,他们都操作共同的变量 i(初始值为 0 )。

这时如果 A 号核⼼执⾏了 i++ 语句的时候,为了考虑性能,使⽤了我们前⾯所说的写回策略,先把值为 1 的执⾏结果写⼊到 L1/L2 Cache 中,然后把 L1/L2 Cache 中对应的 Block标记为脏的,这个时候数据其实没有被同步到内存中的,因为写回策略,只有在 A 号核⼼中的这个 Cache Block 要被替换的时候,数据才会写⼊到内存⾥。


如果这时 B 号核⼼尝试从内存读取 i 变量的值,则读到的将会是错误的值,因为刚才A 号核⼼更新 i 值还没写⼊到内存中,内存中的值还依然是 0。这个就是所谓的缓存⼀致性问

题,A 号核⼼和 B 号核⼼的缓存,在这个时候是不⼀致,从⽽会导致执⾏结果的错误。

三、怎么解决缓存一致性问题?

要保证缓存一致性问题,要保证2点: 写传播(Wreite Propagation)和 事务的串形化(Transaction Serialization)

事务串形化

解释一下,事务串行化:

假设我们有⼀个含有 4 个核⼼的 CPU,这 4 个核⼼都操作共同的变量 i(初始值为 0 )。A号核⼼先把 i 值变为 100,⽽此时同⼀时间,B 号核⼼先把 i 值变为 200,这⾥两个修改,都
会「传播」到 C 和 D 号核⼼。那么问题就来了,C 号核⼼先收到了 A 号核⼼更新数据的事件,再收到 B 号核⼼更新数据的事件,因此 C 号核⼼看到的变量 i 是先变成 100,后变成 200。
⽽如果 D 号核⼼收到的事件是反过来的,则 D 号核⼼看到的是变量 i 先变成 200,再变成100,虽然是做到了写传播,但是各个 Cache ⾥⾯的数据还是不⼀致的。所以,我们要保证 C 号核⼼和 D 号核⼼都能看到相同顺序的数据变化,⽐如变量 i 都是先变
成 100,再变成 200,这样的过程就是事务的串形化。

写传播

写传播很容易就理解,当某个核⼼在 Cache 更新了数据,就需要同步到其他核⼼的Cache ⾥。


写传播就是写传播最常⻅实现的⽅式是总线嗅探(Bus Snooping)。说白了就类似一个消息队列,其他缓存去监听,数据被修改了,操作那个数据都缓存发条消息,其他缓存就都知道了。


可以发现,总线嗅探⽅法很简单, CPU 需要每时每刻监听总线上的⼀切活动,但是不管别的核⼼的 Cache 是否缓存相同的数据,都需要发出⼀个⼴播事件,这⽆疑会加重总线的负载。


总线嗅探并不能保证事务串形化。


于是,有⼀个协议基于总线嗅探机制实现了事务串形化,也⽤状态机机制降低了总线带宽压⼒,这个协议就是 MESI 协议,这个协议就做到了 CPU 缓存⼀致性。

四、MESI 协议

MESI 协议其实是 4 个状态单词的开头字⺟缩写,这四个状态来标记 Cache Line 四个不同的状态,而这些状态是通过总线广播出去的,所以说是基于总线嗅探的,分别是:

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

「已修改」状态就是我们前⾯提到的脏标记,代表该 Cache Block 上的数据已经被更新过,但是还没有写到内存⾥。⽽「已失效」状态,表示的是这个 Cache Block ⾥的数据已经失效
了,不可以读取该状态的数据。
「独占」和「共享」状态都代表 Cache Block ⾥的数据是⼲净的,也就是说,这个时候
Cache Block ⾥的数据和内存⾥⾯的数据是⼀致性的。「独占」和「共享」的差别在于,独占状态的时候,数据只存储在⼀个 CPU 核⼼的 Cache
⾥,⽽其他 CPU 核⼼的 Cache 没有该数据。这个时候,如果要向独占的 Cache 写数据,就可以直接⾃由地写⼊,⽽不需要通知其他 CPU 核⼼,因为只有你这有这个数据,就不存在缓
存⼀致性的问题了,于是就可以随便操作该数据。另外,在「独占」状态下的数据,如果有其他核⼼从内存读取了相同的数据到各⾃的 Cache
,那么这个时候,独占状态下的数据就会变成共享状态。那么,「共享」状态代表着相同的数据在多个 CPU 核⼼的 Cache ⾥都有,所以当我们要更新 Cache ⾥⾯的数据的时候,不能直接修改,⽽是要先向所有的其他 CPU 核⼼⼴播⼀个请
求,要求先把其他核⼼的 Cache 中对应的 Cache Line 标记为「⽆效」状态,然后再更新当前 Cache ⾥⾯的数据。
我们举个具体的例⼦来看看这四个状态的转换:
1. 当 A 号 CPU 核⼼从内存读取变量 i 的值,数据被缓存在 A 号 CPU 核⼼⾃⼰的 Cache ⾥⾯,此时其他 CPU 核⼼的 Cache 没有缓存该数据,于是标记 Cache Line 状态为「独占」,
此时其 Cache 中的数据与内存是⼀致的;
2. 然后 B 号 CPU 核⼼也从内存读取了变量 i 的值,此时会发送消息给其他 CPU 核⼼,由
于 A 号 CPU 核⼼已经缓存了该数据,所以会把数据返回给 B 号 CPU 核⼼。在这个时候, A 和 B 核⼼缓存了相同的数据,Cache Line 的状态就会变成「共享」,并且其Cache 中的数据与内存也是⼀致的;
3. 当 A 号 CPU 核⼼要修改 Cache 中 i 变量的值,发现数据对应的 Cache Line 的状态是共享状态,则要向所有的其他 CPU 核⼼⼴播⼀个请求,要求先把其他核⼼的 Cache 中对应的 Cache Line 标记为「⽆效」状态,然后 A 号 CPU 核⼼才更新 Cache ⾥⾯的数据,
同时标记 Cache Line 为「已修改」状态,此时 Cache 中的数据就与内存不⼀致了。
4. 如果 A 号 CPU 核⼼「继续」修改 Cache 中 i 变量的值,由于此时的 Cache Line 是「已
修改」状态,因此不需要给其他 CPU 核⼼发送消息,直接更新数据即可。
5. 如果 A 号 CPU 核⼼的 Cache ⾥的 i 变量对应的 Cache Line 要被「替换」,发现Cache Line 状态是「已修改」状态,就会在替换前先把数据同步到内存。所以,可以发现当 Cache Line 状态是「已修改」或者「独占」状态时,修改更新其数据不需
要发送⼴播给其他 CPU 核⼼,这在⼀定程度上减少了总线带宽压⼒。

对于在「已修改」或者「独占」状态的 Cache Line,修改更新其数据不需要发送⼴播给其他 CPU 核⼼。

这个MESI,我这里只是简诉,Java中的volatile保证的可见性,底层的原理就是依靠于MESI,建议这个协议还是有必要了解下。

相关实践学习
CentOS 7迁移Anolis OS 7
龙蜥操作系统Anolis OS的体验。Anolis OS 7生态上和依赖管理上保持跟CentOS 7.x兼容,一键式迁移脚本centos2anolis.py。本文为您介绍如何通过AOMS迁移工具实现CentOS 7.x到Anolis OS 7的迁移。
目录
相关文章
|
1月前
|
存储 缓存 芯片
让星星⭐月亮告诉你,当我们在说CPU一级缓存二级缓存三级缓存的时候,我们到底在说什么?
本文介绍了CPU缓存的基本概念和作用,以及不同级别的缓存(L1、L2、L3)的特点和工作原理。CPU缓存是CPU内部的存储器,用于存储RAM中的数据和指令副本,以提高数据访问速度,减少CPU与RAM之间的速度差异。L1缓存位于处理器内部,速度最快;L2缓存容量更大,但速度稍慢;L3缓存容量最大,由所有CPU内核共享。文章还对比了DRAM和SRAM两种内存类型,解释了它们在计算机系统中的应用。
74 1
|
5天前
|
运维 Prometheus 监控
如何在测试环境中保持操作系统、浏览器版本和服务器配置的稳定性和一致性?
如何在测试环境中保持操作系统、浏览器版本和服务器配置的稳定性和一致性?
|
1月前
|
监控 异构计算
Jetson 学习笔记(八):htop查看CPU占用情况和jtop监控CPU和GPU
在NVIDIA Jetson平台上使用htop和jtop工具来监控CPU、GPU和内存的使用情况,并提供了安装和使用这些工具的具体命令。
111 0
|
5月前
|
存储 缓存 算法
数据结构和算法学习记录——总结顺序表和链表(双向带头循环链表)的优缺点、CPU高速缓存命中率
数据结构和算法学习记录——总结顺序表和链表(双向带头循环链表)的优缺点、CPU高速缓存命中率
49 0
|
6月前
|
存储
计算机组成原理(7)----CPU内部单总线数据通路
计算机组成原理(7)----CPU内部单总线数据通路
368 0
|
6月前
|
存储
计算机组成原理(5)----CPU的基本结构
计算机组成原理(5)----CPU的基本结构
174 0
|
3月前
|
存储 缓存 数据处理
计算机临时存储CPU运算数据
【8月更文挑战第4天】
65 8
|
3月前
|
存储 固态存储 测试技术
|
4月前
|
编译器 芯片
计算机中CPU 架构
【7月更文挑战第27天】
66 2
|
4月前
|
存储 缓存 数据处理
计算机中 中央处理器 (CPU)
【7月更文挑战第27天】
59 2