Memory Consistency and Cache Coherence—— cache一致性协议(MESI)

    cache监听一致性主要是获得cache的总线访问权,比如core1和core2同时写入相同的地址,会交由总线进行仲裁,确定哪个核先写入,在获得写入权限后,会通过总线广播使地址失效。一般的smp架构cpu cache结构如下图:

Memory Consistency and Cache Coherence—— cache一致性协议(MESI)_第1张图片

其中分为三级cache,第一级和第二级cache是处理器独有的,第三级cache是共享的,L1cache分为指令cache,数据cache。intel corei7的L1 指令cache是四路组相联(cache分组,每组四行,每行64字节,从内存加载到cache时,每次读取64字节),数据cache数八路组相联。所有的数据存储都是通过cache进行,比如读一个地址的数据:如果L1cache未命中,则读取L2cache,如果L2未命中则读取L3,如果L3未命中,则读取物理内存,读取时间会越来越慢,L1访问速度大概2-4个时钟周期,L2大概10个时钟周期,L3 30-40时钟周期。读取成功后会根据L1cache的块大小,将一块数据读取到cache,比如块大小是64字节,则一次会从内存中读取64字节读到cache。

  读写cache需要cache一致性协议保证数据正确,MESI协议规定了一块内存的五种状态:Modified(M,修改),Exclusive(E,独占),Share(S,共享),Invalid(I,无效)。

   首先看最基本的MSI协议,也可以叫做写入失效协议。如果同时有多个处理器写入,总线会进行串行化,同一时刻只会有一个处理器获得访问权。比如处理器c1,c2对变量m进行读写,采用cache采用回写方式:

 

处理器操作 总线操作 c1 缓存内容 c2缓存内容 存储器m所在地址内容
        0
c1读取m 缓存没有m,从存储器读取 0   0
c2读取m 缓存没有m,从存储器读取 0 0 0
c1写入1到m 通知c2缓存的m值,使其失效 1   0
c2读取m的值 缓存没m,从c1的缓存中读出(采用回写方式,并且更新到存储器) 1 1 1

其中c2第二次读取m时,c1会将m的最新值返回给c2,并且更新存储器m的值,c1,c2  m的值会变成共享状态。

在详细介绍MSI协议前,再额外介绍两个技术:

 

 处理器同时写入相同的地址串行化技术实现:如果两个处理器同时写入共享块,当它们争用总线时会串行安排它们广播其失效操作的尝试。第一个获得总线访问权限的处理器会使它正写入块的所有其它处理器上的副本失效。如果其它处理器尝试写入同一块,则由总线实现写入操作的串行化。也就是说在获得总线访问权限之前,无法完成对共享块的写入操作。所有的一致性机制都需要某种方法实现对共享缓存块的串行访问。

    查找最新值在不同的缓存写回方式下的实现:

     缓存直写方式:在处理器对缓存更新时,会同时写入到存储器和低一级的cache,这种方式会大量占用总线。这种方式一致性协议实现比较简单,因为所有的数据都会更新到存储器,所以其他处理器读取存储器时都是最新值。

     缓存写回方式:数据的更新并不会立马反应到存储器,而是在cache替换时或者变成共享(S)状态时,发现数据有变动,才会将最新的数据更新到存储器,这种方式占用总线少,大多数处理器的cache使用这种方式。这种方式实现一致性协议比较复杂,因为最新值可能存在私有缓存,而不是共享缓存或者存储器,但是写回缓存可以为缓存缺失和写入操作使用相同的监听机制:每个处理器都监听放在共享总线上的所有地址。如果发现自己有被请求缓存块的最新值,它会提供该缓存块响应请求,并终止存储器的访问。由于需要从另一个处理器的私有cache(L1或L2)提取数据,所以访问时间会变慢,大概是L3cache的访问速度。

MSI协议 操作分类,状态分类,请求回应 表

 

请求源 请求类型 所寻址缓存块状态 缓存操作类型 请求结果
处理器 读取命中 共享(S)或已修改(M) 正常命中 读取本地缓存数据,并且命中
处理器 读取缺失 无效(I) 正常缺失 将读取缺失广播到总线
处理器 读取缺失 共享(S) 替换 地址冲突缺失,需要替换存在的数据块,将读取缺失广播到总线
处理器 读取缺失 已修改(M) 替换 地址冲突缺失;将缓存快写回存储器,将读取缺失广播到总线
处理器 写命中 已修改(M) 正常命中 将数据写入本地缓存
处理器 写命中 共享(S) 一致性 将失效操作广播到总线,使其它缓存了此块处理器缓存状态变为失效
处理器 写缺失 无效 (I) 正常缺失 将写缺失广播到总线
处理器 写缺失 共享(S) 替换 地址冲突缺失,将写缺失广播到总线
处理器 写缺失 已修改 (M) 替换 地址冲突缺失,将缓存块写回到存储器,并将写缺失广播到总线
总线 读取缺失 共享(S) 无操作 其他处理器缓存或者存储器将缺失的数据提供给广播读取缺失的处理器
总线 读取缺失 已修改(M) 一致性 尝试共享数据,将缓存块放到总线,并设置标志位为共享(S)
总线 失效 共享(S) 一致性 使共享块状态由共享(S)变为失效(I  )
总线 写缺失 共享(S) 一致性 尝试写共享块,使缓存块失效
总线 写缺失 已修改(M) 一致性 尝试将独占块写到其他位置,写回该缓存块,并在本地缓存中使其状态时效
         
         
         
         
         

MSI状态转换图如下:

 

Memory Consistency and Cache Coherence—— cache一致性协议(MESI)_第2张图片

 

MSI协议是最基本最简单的cache一致性协议,很多现代处理器都会加入Exclusive(E)独占状态,这样在处理一些操作时可以减少总线通信。比如在先读取块然后写入块的情况下效率就很高,在MSI协议下,读取块会变为S状态,然后再写入该块会导致cpu发送给总线一个使其它cpu持有该块失效的信号,如果该块其它cpu就没有,那就是一次无效的信号。在MESI协议下,读取内存块如果其它cpu都是I状态,则当前cpu该块会变成E状态,然后写入的时候直接写就可以,不需要发送使该块失效的信号。

所以MESI协议首先要解决,如何确定没有其它共享者,而让本块变为E状态,比如可以添加一根共享信号线做或运算,每个cpu在读取内存修改状态时都要判断共享信号线,如果共享信号线为1,则将cache块状态置为S,否则cache状态块置为E。MESI协议和MSI协议最大不同就是其他状态到S or E状态,还有E到M状态,其他和MSI协议没啥区别。MESI转换图如下:

Memory Consistency and Cache Coherence—— cache一致性协议(MESI)_第3张图片

和MSI的主要不同就是E和其它状态的转换,其中E到M直接在cpu cache内部转换不需要通过总线通知其它cpu。

MESI协议在多核cpu下保证了cache数据的一致性,使每个cpu在读取数据时都是读到的最新的数据,也遵守了SWMR(单写多读)策略,写的时候只能有一个cpu被总线仲裁成功。

 

 

你可能感兴趣的:(计算机体系结构)