目标是架构师,但到现在还不会MESI?

本文深入探讨了CPU高速缓存的作用,基于局部性原理解释了其存在的必要性,并详细阐述了多级缓存结构。重点介绍了多核CPU中的一致性协议MESI,包括缓存状态及状态转换,并通过实例解析了多核环境下的数据同步。此外,还提到了伪共享问题及其解决方案,最后提供了技术进阶和面试资料。

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

最近在补充学习MESI 为了记录自己的努力成长,同时让大家和我一起成长特地把自己关于MESI的学习做成了笔记分享给大家 :

1.CPU为何要有高速缓存

CPU在摩尔定律的指导下以每18个月翻一番的速度在发展,然而内存和硬盘的发展速度远远不及CPU。这就造成了高性能能的内存和硬盘价格及其昂贵。然而CPU的高度运算需要高速的数据。为了解决这个问题,CPU厂商在CPU中内置了少量的高速缓存以解决I\O速度和CPU运算速度之间的不匹配问题。

在CPU访问存储设备时,无论是存取数据抑或存取指令,都趋于聚集在一片连续的区域中,这就被称为局部性原理。

  • 时间局部性(Temporal Locality如果一个信息项正在被访问,那么在近期它很可能还会被再次访问。比如循环、递归、方法的反复调用等。

  • 空间局部性(Spatial Locality如果一个存储器的位置被引用,那么将来他附近的位置也会被引用。比如顺序执行的代码、连续创建的两个对象、数组等。

带有高速缓存的CPU执行计算的流程

  • 1. 程序以及数据被加载到主内存

  • 2. 指令和数据被加载到CPU的高速缓存

  • 3. CPU执行指令,把结果写到高速缓存

  • 4. 高速缓存中的数据写回主内存

目前流行的多级缓存结构

由于CPU的运算速度超越了1级缓存的数据I\O能力,CPU厂商又引入了多级的缓存结构。

多级缓存结构

       

2.多核CPU多级缓存一致性协议MESI

多核CPU的情况下有多个一级缓存,如何保证缓存内部数据的一致,不让系统数据混乱。这里就引出了一个 一致性的协议MESI

MESI协议缓存状态

MESI 是指4中状态的首字母。每个Cache line有4个状态,可用2个bit表示,它们分别是:

缓存行(Cache line:缓存存储数据的单元。注意:对于M和E状态而言总是精确的,他们在和该缓存行的真正状态是一致的,而S状态可能是非一致的。如果 一个缓存将处于S状态的缓存行作废了,而另一个缓存实际上可能已经独享了该缓存行,但是该缓存却不会 将该缓存行升迁为E状态,这是因为其它缓存不会广播他们作废掉该缓存行的通知,同样由于缓存并没有保 存该缓存行的copy的数量,因此(即使有这种通知)也没有办法确定自己是否已经独享了该缓存行。从上面的意义看来E状态是一种投机性的优化:如果一个CPU想修改一个处于S状态的缓存行,总线事务需

要将所有该缓存行的copy变成invalid状态,而修改E状态的缓存不需要使用总线事务。

MESI状态转换

理解该图的前置说明:

1.触发事件

2.cache分类:

前提:所有的cache共同缓存了主内存中的某一条数据。

本地cache:指当前cpu的cache。

触发cache:触发读写事件的cache。

其他cache:指既除了以上两种之外的cache。

注意:本地的事件触发 本地cache和触发cache为相同

上图的切换解释:

下图示意了,当一个cache line的调整的状态的时候,另外一个cache line 需要调整的状态。

举个栗子来说:

假设cache 1 中有一个变量x = 0的cache line 处于S状态(共享)。

那么其他拥有x变量的cache 2、cache 3等x的cache line调整为S状态(共享)或者调整为 I 状态(无效)。

多核缓存协同操作

假设有三个CPU A、B、C,对应三个缓存分别是cache a、b、 c。在主内存中定义了x的引用值为0。

       

        

单核读取

那么执行流程是:

CPU A发出了一条指令,从主内存中读取x。

从主内存通过bus读取到缓存中(远端读取Remote read),这是该Cache line修改为E状态(独享).

       

        

双核读取

那么执行流程是:

  1. CPU A发出了一条指令,从主内存中读取x。

  2. CPU A从主内存通过bus读取到 cache a中并将该cache line 设置为E状态。

  3. CPU B发出了一条指令,从主内存中读取x。

  4. CPU B试图从主内存中读取x时,CPU A检测到了地址冲突。这时CPU A对相关数据做出响应。此时x 存储

  5. 于cache a和cache b中,x在chche a和cache b中都被设置为S状态(共享)。

同步数据

那么执行流程是:

  1. CPU B 发出了要读取x的指令。

  2. CPU B 通知CPU A,CPU A将修改后的数据同步到主内存时cache a 修改为E(独享)

  3. CPU A同步CPU B的x,将cache a和同步后cache b中的x设置为S状态(共享)

       

3.缓存行伪共享

什么是伪共享?

CPU缓存系统中是以缓存行(cache line)为单位存储的。目前主流的CPU Cache 的

Cache Line 大小都是64Bytes。在多线程情况下,如果需要修改“共享同一个缓存行的变 量”,就会无意中影响彼此的性能,这就是伪共享(False Sharing)。

举个例子: 现在有2个long 型变量 a 、b,如果有t1在访问a,t2在访问b,而a与b刚好在同一个

cache line中,此时t1先修改a,将导致b被刷新!

怎么解决伪共享?

Java8中新增了一个注解:@sun.misc.Contended。加上这个注解的类会自动补齐缓

存行,需要注意的是此注解默认是无效的,需要在jvm启动时设置 -XX:RestrictContended 才会生效。

到这里我们对于MESI已经有了一定的了解,除开今天分享的内容,我这里专门和几个大佬准备了一份技术进阶+项目经验+面试突击的资料,包含了十多个互联网大厂的面试题、面经汇总和20个技术栈资料合集,吃透这份资料,技术面和面试关完全不是问题!同时还有大厂项目实战的视频解析,那些你缺乏的项目经验都可以从中积累。

在这期间有面试的,可以根据下面的资料抓紧准备一下,对大厂面试、技术进阶和跳槽都非常有用!!!

 点击下方名片可以直接领取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值