棋子 · 2021年06月07日

CPU设计之Cache -- 广播式一致性协议(一)

前面提到,根据一致性消息传播给谁,一致性协议可以分为广播式和目录式两种。首先来看基于总线的广播式一致性协议。

写直达策略的一致性协议

最简单的一致性协议是基于写直达(Write Through)策略的。假设一个单级缓存系统,处理器缓存的请求包含:

  1. PrRd:处理器请求从缓存中读出;
  2. PrWr:处理器请求向缓存中写入。

总线侦听的请求包括:

  1. BusRd:总线侦听到一个来自另一个处理器的读出缓存请求;
  2. BusWr:总线侦听到一个来自另一个处理器的写入缓存请求。

再来复习一下写直达策略,也就是缓存中任何一个字节的修改都会被立即传播到外层的存储层次。所以BusWr也意味着另一个处理器向主存中写入数据。而且,在写直达里是没有dirty状态的,因为所有对于缓存的写操作都被直接写入到主存,所有缓存的值都是干净的。那么缓存块的状态包括以下几种:

  1. Valid(V):缓存块有效且干净,与主存中的相同;
  2. Invalid(I):缓存块无效或尚未使用,访问该缓存块会导致缺失。

再假设使用写不分配(Write Non-allocate)和写无效(Write Invalidate)两种策略,接下来看一下缓存状态是如何切换的。

首先考虑缓存块为“I”时,当处理器发出读请求,会导致缓存缺失。这就需要把数据从主存加载进缓存,总线上产生了一个BusRd的请求。当数据被加载进缓存的同时,缓存块状态变为“V”。当处理器发出写请求,因为采用写不分配(不需要先将数据从主存加载进缓存),写操作触发BusWr,此时缓存块状态仍为“I”。

接下来考虑缓存块状态为“V”,当处理器发出读请求,缓存命中,数据直接返回给处理器,不触发总线事务,缓存块状态仍是“V”。当处理器发出写请求,该缓存块被更新,并且触发BusWr,缓存块状态仍为“V”。

对于侦听器过滤器(Snoop Filter)来说,如果缓存块状态是“I”,那么BusRd和BusWr不会产生影响,缓存块状态还是“I”。如果缓存块状态是“V”,BusRd意味着其它的处理器遇到了缺失,需要从主存中读取数据,该缓存块的状态保持“V”不变;但是一旦侦听到BusWr,那就意味着其他的处理器要写入新数据,该缓存块的状态需要变为“I”。

WeChat Image_20210607101801.png
图1 写直达的缓存一致性协议状态转换

上图左边是处理器的请求响应,右侧是侦听器的请求响应。如果是具体实现,两边可以合并在一起做成一个有限状态机。

还记得吗?写直达策略的最大缺点是占用很大的带宽。对于多级缓存系统,处理器芯片最外层的高速缓存,由于片外带宽有限,往往采用写回策略;而对于内层高速缓存,由于片上带宽较大,因此往往采用写直达策略。

写回策略的一致性MSI协议

写回策略与写直达策略相比,占用的带宽小。由于修改的数据不会马上更新到主存,所以缓存块要增加一个dirty位。

在MSI协议中,处理器的缓存请求包含:

  1. PrRd,处理器请求从缓存块中读出;
  2. PrWr,处理器请求向缓存块中写入。

总线侦听的请求包含:

  1. BusRd,总线侦听到一个来自另一个处理器的读出缓存请求;
  2. BusRdX,总线侦听到一个来自另一个处理器的“读独占”(或者是写)缓存请求;
  3. Flush,总线侦听到一个缓存块被另一个处理器写回到主存的请求。

每一个缓存块的状态包含:

  1. Modified(M):缓存块有效,并且其数据与主存中的原始数据不同,这个缓存块是“dirty”的;
  2. Shared(S):缓存块是有效的且有可能被其他处理器共享,这个缓存块是“clean”的;
  3. Invalid(I):缓存块无效。

假设使用写分配和写无效缓存一致性策略。写回缓存的MSI一致性策略有限状态机如图所示。处理器方面的请求响应在左侧,总线侦听的请求响应在右侧。

WeChat Image_20210607101815.png
图2 写回缓存的MSI一致性协议状态转换图

先看处理器请求端,如果缓存块状态是“I”,当处理器发出读请求时,发生cache miss,需要把数据加载进缓存,总线上产生了一个BusRd事务。当数据被加载完,缓存块的状态变为“S”,这里S状态不区分该缓存块是不是唯一的。当处理器发出写请求时,由于是写分配,缓存块要加载,故触发BusRdX,其他缓存响应后将它们的拷贝变成“I”。发出写请求的处理器得到该缓存块后将状态变为“M”。

接下来再看如果缓存块的状态是“S”时,处理器发出读请求,cache hit,不会触发总线事务。如果处理器发出写请求,由于不知道是不是还存在其它的副本,所以必须要触发BusRdX通知其它处理器。

最后来看如果缓存块的状态是“M”,不管处理器发出读或写请求都不会触发总线事务。

再看右边的总线侦听。对于其它的缓存来说,如果缓存块的状态是“I”,侦听到BusRd和BusRdX也无所谓。如果状态是“S”,侦听到BusRd说明其它的处理器遇到了读缺失,需要加载数据,对自己没有影响;如果是侦听到BusRdX,说明有其它处理器要修改这个缓存块,自己的拷贝不是最新的数据,因此要把状态变为“I”。如果当前状态是“M”,侦听到BusRd,说明其它处理器需要加载该缓存块的最新数据,所以要把自己的拷贝全部清空(Flush)出去并把状态变为“S”;侦听到BusRdX,说明其它处理器要修改该块,所以把自己的拷贝清空,并把状态改为“I”,这个flush动作是必须的,因为其它处理器要修改的和自己修改的不一定是同一个字节。

还记得吗?S状态不区分该缓存块是不是唯一的。所以MSI协议有一个严重的缺陷,假设有一个处理器想要读一些块并对他们进行写入,这里没有其他处理器共享的块。这种情况下,对于每一个读-写操作序列,会触发两个总线事务:一个BusRd将块变为S状态,以及一个BusRdX以无效化其它缓存拷贝。该BusRdX是没有用的,因为没有其它拷贝,但是一致性控制器不知道这一点。大多数BusRdX请求是没有必要的。这个缺陷会影响诸如顺序执行程序等几乎没有数据共享的程序在执行时的性能。

要克服这个缺陷,需要增加一个新的状态来区分缓存块是干净且唯一还是存在多个拷贝。下周接着讲MESI。

作者:老秦谈芯
来源:https://mp.weixin.qq.com/s/Ew7uDPqLTaBOnFSyhT4Pkw
作者微信公众号
qrcode_LaoQinTanXin_1.jpg

相关文章推荐

更多IC设计技术干货请关注IC设计技术专栏。
推荐阅读
关注数
19009
内容数
1294
主要交流IC以及SoC设计流程相关的技术和知识
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息