Cache一致性协议之MESI

本文深入探讨了处理器缓存一致性的重要协议——MESI,详细解析了其四种状态(Modified, Exclusive, Shared, Invalid)及其转换机制。通过具体示例,阐述了单核与多核环境下缓存行的状态变化,以及处理器如何通过监听机制维护数据一致性。

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

处理器上有一套完整的协议,来保证Cache一致性。比较经典的Cache一致性协议当属MESI协议,奔腾处理器有使用它,很多其他的处理器都是使用它的变种。

单核Cache中每个Cache line有2个标志:dirty和valid标志,它们很好的描述了Cache和Memory(内存)之间的数据关系(数据是否有效,数据是否被修改),而在多核处理器中,多个核会共享一些数据,MESI协议就包含了描述共享的状态。

         在MESI协议中,每个Cache line有4个状态,可用2个bit表示,它们分别是: 

状态

描述

M(Modified)

这行数据有效,数据被修改了,和内存中的数据不一致,数据只存在于本Cache中。

E(Exclusive)

这行数据有效,数据和内存中的数据一致,数据只存在于本Cache中。

S(Shared)

这行数据有效,数据和内存中的数据一致,数据存在于很多Cache中。

I(Invalid)

这行数据无效。

MESI状态

           M(Modified)和E(Exclusive)状态的Cache line,数据是独有的,不同点在于M状态的数据是dirty的(和内存的不一致),E状态的数据是clean的(和内存的一致)。

          S(Shared)状态的Cache line,数据和其他Core的Cache共享。只有clean的数据才能被多个Cache共享。

          I(Invalid)表示这个Cache line无效。

 

          E状态示例如下:

只有Core 0访问变量x,它的Cache line状态为E(Exclusive)。

S状态示例如下:


 

 3个Core都访问变量x,它们对应的Cache line为S(Shared)状态。

    M状态和I状态示例如下:

M状态和I状态

            Core 0修改了x的值之后,这个Cache line变成了M(Modified)状态,其他Core对应的Cache line变成了I(Invalid)状态。

 

        在MESI协议中,每个Cache的Cache控制器不仅知道自己的读写操作,而且也监听(snoop)其它Cache的读写操作。每个Cache line所处的状态根据本核和其它核的读写操作在4个状态间进行迁移。

       MESI协议状态迁移图如下:


 

MESI协议状态迁移图

        在上图中,Local Read表示本内核读本Cache中的值,Local Write表示本内核写本Cache中的值,Remote Read表示其它内核读其它Cache中的值,Remote Write表示其它内核写其它Cache中的值,箭头表示本Cache line状态的迁移,环形箭头表示状态不变。

        当内核需要访问的数据不在本Cache中,而其它Cache有这份数据的备份时,本Cache既可以从内存中导入数据,也可以从其它Cache中导入数据,不同的处理器会有不同的选择。MESI协议为了使自己更加通用,没有定义这些细节,只定义了状态之间的迁移,下面的描述假设本Cache从内存中导入数据。

         

MESI状态之间的迁移过程如下:

当前状态

 

MESI状态迁移

           AMD的Opteron处理器使用从MESI中演化出的MOESI协议,O(Owned)是MESI中S和M的一个合体,表示本Cache line被修改,和内存中的数据不一致,不过其它的核可以有这份数据的拷贝,状态为S。

         Intel的core i7处理器使用从MESI中演化出的MESIF协议,F(Forward)从Share中演化而来,一个Cache line如果是Forward状态,它可以把数据直接传给其它内核的Cache,而Share则不能。
--------------------- 
 

MESI协议是一种广泛使用的缓存一致性协议,用于在多处理器系统中维护各个处理器缓存之间数据的一致性。该协议通过定义缓存行的四种状态以及这些状态之间的转换规则,确保所有处理器对共享内存的数据访问保持一致。 ### MESI协议的四种状态 1. **Modified (M)**:该缓存行中的数据是脏的(即已经被修改),并且只存在于当前处理器的缓存中。此时,主存中的数据已经过时。 2. **Exclusive (E)**:该缓存行中的数据与主存中的数据一致,并且只存在于当前处理器的缓存中。 3. **Shared (S)**:该缓存行中的数据与主存中的数据一致,并且可能存在于多个处理器的缓存中。 4. **Invalid (I)**:该缓存行无效,不能使用。 ### 状态转换流程 MESI协议的状态转换是由处理器执行的读写操作以及总线监听机制触发的。以下是主要的状态转换过程: #### 从**Invalid (I)** 到其他状态 - **I → E**:当处理器读取一个不在其缓存中的数据,并且该数据在其他处理器的缓存中不存在或处于无效状态时,该缓存行进入**专有态**。 - **I → S**:当处理器读取一个数据,而该数据在其他处理器的缓存中处于**共享态**或**专有态**时,该缓存行进入**共享态**。 - **I → M**:当处理器写入一个不在其缓存中的数据,并且该数据在其他处理器的缓存中不存在或处于无效状态时,该缓存行进入**修改态**。 #### 从**Exclusive (E)** 到其他状态 - **E → M**:当处理器对该缓存行进行写操作时,该缓存行变为**修改态**。 - **E → S**:如果其他处理器请求读取该缓存行的数据,则该缓存行变为**共享态**。 - **E → I**:如果其他处理器对该缓存行进行写操作,则该缓存行变为**无效态**。 #### 从**Shared (S)** 到其他状态 - **S → M**:当处理器对该缓存行进行写操作时,它会向总线广播写请求,其他处理器将其缓存行置为无效,该缓存行变为**修改态**。 - **S → I**:如果其他处理器对该缓存行进行写操作,则该缓存行变为**无效态**。 #### 从**Modified (M)** 到其他状态 - **M → E**:当处理器将该缓存行的数据写回主存后,若其他处理器未持有该数据,则该缓存行变为**专有态**。 - **M → S**:如果其他处理器请求读取该缓存行的数据,则该缓存行变为**共享态**。 - **M → I**:如果其他处理器对该缓存行进行写操作,则该缓存行变为**无效态**。 ### 示例 假设有一个双核系统,Core A Core B 都访问同一个内存地址: 1. 初始时,该地址的数据在主存中,Core A Core B 的缓存中都没有该数据。 2. Core A 读取该地址的数据,其缓存行状态变为**专有态**。 3. Core B 也读取该地址的数据,Core A 的缓存行状态变为**共享态**,Core B 的缓存行状态也为**共享态**。 4. Core A 对该地址进行写操作,它会向总线广播写请求,Core B 将其缓存行置为无效,Core A 的缓存行状态变为**修改态**。 5. 如果 Core B 再次读取该地址的数据,Core A 会将其缓存行的数据写回到主存,并将缓存行状态变为**共享态**,Core B 的缓存行状态也变为**共享态**。 ```python # 模拟MESI状态转换的简单示例 class CacheLine: def __init__(self): self.state = 'I' # 初始状态为无效态 def read(self, other_caches): if self.state == 'I': for cache in other_caches: if cache.state == 'M': # 其他缓存中有修改态的数据,需要先写回主存 cache.state = 'I' self.state = 'S' elif self.state == 'E': pass # 专有态可以直接读取 elif self.state == 'S': pass # 共享态可以直接读取 def write(self, other_caches): if self.state == 'I': for cache in other_caches: if cache.state in ['S', 'E']: cache.state = 'I' self.state = 'M' elif self.state == 'E': self.state = 'M' elif self.state == 'S': for cache in other_caches: if cache.state in ['S', 'E']: cache.state = 'I' self.state = 'M' # 创建两个缓存行 cache_a = CacheLine() cache_b = CacheLine() # Core A读取 cache_a.read([cache_b]) print(f"Cache A state after read: {cache_a.state}") # 输出: Cache A state after read: S # Core B读取 cache_b.read([cache_a]) print(f"Cache B state after read: {cache_b.state}") # 输出: Cache B state after read: S # Core A写入 cache_a.write([cache_b]) print(f"Cache A state after write: {cache_a.state}") # 输出: Cache A state after write: M print(f"Cache B state after A's write: {cache_b.state}") # 输出: Cache B state after A's write: I ``` ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值