MESI-缓存一致性
2021-07-06 14:38:39 0 举报
AI智能生成
MESI-缓存一致性
作者其他创作
大纲/内容
CPU 高速缓存与主存不一致性的维护方式
动态演示网址:VivioJS MESI animation help (tcd.ie)
单核 CPU 下的缓存一致性Cache-主存一致性
多核 CPU 的问题
怎么拿到其他CPU还未同步回主存的最新数据
CPU 修改了数据,怎么通知其他 CPU 的缓存失效
缓存一致性特性
写传播(Write Propagation)
Cache 数据更新,必须能够传播到其他的对应节点的 Cache Line 里。
事务串行化(Transaction Serialization)
在一个 CPU 核心里面的读取和写入,在其他的节点看起来,顺序是一样的
解决写传播(Write Propagation)
写传播(Write Propagation)的实现方式
写失效:当一个CPU修改了数据,如果其他CPU有该数据,则通知其为无效。
写更新(写广播):当一个CPU修改了数据,如果其他CPU有该数据,则通知其更新数据。
总线嗅探机制
广播 CPU 的读写请求
所有 CPU 监听总线上的所有活动
解决事务串行化(Transaction Serialization)
总线锁:在多 CPU 情况下,某个 CPU 对共享变量操作时,在总线上发出一个 #LOCK信号,总线把 CPU 和内存之间的通信锁住了,其他 CPU 不能操该内存地址的数据。
缓存锁:降低了锁的粒度,基于缓存一致性协议来实现。
MESI
特性
缓存一致性特性:写传播(Write Propagation)、事务串行化(Transaction Serialization)
写回法(Write-back):只写入 Cache,当数据被替换回主存时才写回到主存。因此需要标识是一致(S、E)还是不一致(M)
写失效:当一个CPU修改了数据,如果其他CPU有该数据,则通知其为无效。
总线嗅探机制
缓存锁:降低了锁的粒度,基于缓存一致性协议来实现。
Cache Line 四种状态(2 bit 表示)
M:已修改(Modified)
当前 CPU 缓存有最新数据, 其他 CPU 拥有失效数据,当前 CPU 数据与内存不一致,但以当前 CPU 数据为准。
E:独占(Exclusive)
只有当前 CPU 有数据,其他 CPU 没有该数据,当前 CPU 数据与内存数据一致。
S:共享(Shared)
当前 CPU 与其他 CPU 拥有相同数据,并与内存中数据一致。
I:已失效(Invalidated)
当前 CPU 数据失效,其他 CPU 数据可能有可能无,数据应从内存中读取,且当前 CPU 与 内存数据不一致。
四种操作
Local Read(LR):当前 CPU 读操作
Local Write(LW):当前 CPU 写操作
Remote Read(RR):其他 CPU 读操作
Remote Write(RW):其他 CPU 写操作
状态流转
当处于 S:共享(Shared),Local Write(LW):当前 CPU 写操作
先广播一个 Invalidate 请求(RFO),要求其他 CPU 失效缓存,变为 I:已失效(Invalidated),响应 Invalidate ACK
收到 Invalidate ACK,再更新本地缓存,变成 M:已修改(Modified)
当处于 I:已失效(Invalidated),Local Write(LW):当前 CPU 写操作
先广播一个 Read Invalidate 请求(Read + Invalidate),读取最新数据的同时,要求其他 CPU 失效缓存,变为 I:已失效(Invalidated),并响应 Invalidate ACK
收到 Invalidate ACK,再更新本地缓存,变成 M:已修改(Modified)
当处于 M:已修改(Modified),Remote Write(RW):其他 CPU 写操作 或者 Remote Read(RR):其他 CPU 读操作
当前CPU需要将修改写回内存
其他 CPU 才能读取内存
问题:在 MESI 中,依赖总线嗅探机制,整个过程是串行的,可能会发生阻塞。
若 CPU0 发生 LW,首先需要发送一个 Invalidate 消息给到其他缓存了该数据的 CPU1。并且要等待确认回执。CPU0 在这段时间内都会处于阻塞状态。
对于 CPU1 来说, CPU0 发生 RW,CPU1 需要失效缓存。 当其高速缓存压力很大时,要求实时的处理失效事件也存在一定的困难,会有一定的延迟。
CPU0 等待延迟 = Invalidate请求响应传送延迟 + CPU1 处理 Invalidate 延迟
优化:解决问题
写缓冲区(Store Buffer)
写缓冲区是属于每个 CPU 的
每当发生LW,当前 CPU 不再阻塞地等待其他 CPU 的确认或读取到最新值,而是直接将更新的值直接写入写缓冲区,然后继续执行后续指令。
等失效响应到达,删除 Store Buffer,写入 Cache。
Store Fowarding : 在进行LR 时,CPU 会先在写缓冲区中查询记录是否存在,如果存在则会从写缓冲区中直接获取。
失效队列(InvalidQueue)
失效队列也是属于每个 CPU
使用失效队列后,发生RW 对应的 CPU 缓存不再同步地失效缓存并发送确认回执,而是将失效消息放入失效队列,立即发送确认回执。
后续 CPU 会在空闲是对失效队列中的消息进行处理,将对应的 CPU 缓存失效。
写缓冲区(Store Buffer)的指令失序
问题
如果前一个值 a 是 S,所以写入由于要发送 Invalidate,直接写到了 Store Buffer。
而下一个值 b 是 E,直接写到 Cache。
而这时,另一个 CPU 读取 a、b,b 读到了新值(同步会内存),a 却是旧值(还未处理 Store Buffer)
优化:Write Barrier
将 Write Barrier 之前所有操作的 Cache Line 都打上标记,Barrier 之后的写入操作不能直接操作 Cache Line 而也要先写 Store Buffer 。
只是这种因为 Barrier 关系也写入 Store Buffer 的 Cache Line 不用打特殊标记。
等 Store Buffer 内带着标记的写入因为收到 Invalidate Ack 而能写 Cache Line 后,这些没有打标记的写入操作才能一并写入 Cache Line。
失效队列(Invalidate Queue)的指令失序
问题
Invalidate 消息被放入 Invalidate Queue,还未被处理
发生 LR,读取到旧值(本应该失效的)
优化:Read Barrier
标记 Invalidate Queue 上的 Cache Line,之后继续执行别的指令
直到看到下一个 Load 操作要从 Cache Line 里读数据了,CPU 才会等待 Invalidate Queue 内所有刚才被标记的 Cache Line 都处理完才继续执行下一个 Load
注意:如果在标记之后,又有新的 Invalidate 消息,那相关的 Cache Line 是没有被标记的,下一次 Load 直接读取 Cache。
读写屏障的实现方式:软件指令 LOCK
LOCK 指令前缀有以下两大作用:
开启总线锁或者缓存锁(通过在总线上发送 #LOCK 信号。)
与被修饰的汇编指令一起提供内存屏障的效果
0 条评论
下一页