计算机系统结构-第5章-监听式协议
监听式协议******:
思想:
每个Cache除了包含物理存储器中块的数据拷贝之外,也保存着各个块的共享状态信息。
Cache通常连在共享存储器的总线上,当某个Cache需要访问存储器时,它会把请求放到总线上广播出去,其他各个Cache控制器通过监听总线(它们一直在监听)来判断它们是否有总线上请求的数据块。如果有,就进行相应的操作。
3个关键:
1:处理器之间通过一个可以实现广播的互连机制相连 (链接)
2:当一个处理器的Cache响应本地CPU的访问时,如果它涉及全局操作,其Cache控制器就要在获得总线的控制权后,在总线上发出相应的消息(发送者)
3:所有处理器都一直在监听总线,它们检测总线上的地址在它们的Cache中是否有副本。若有,则响应该消息,并进行相应的操作 。(接受者)
写操作的串行化:由总线实现(获取总线控制权的顺序性)
发送到总线的信息:1-读不命中 ;2-写不命中
这个时候需要通过总线找到相应的数据块的最新版本,然后调入本地的cache
(cache的种类:
写直达Cache:因为所有写入的数据都同时被写回主存,所以从主存中总可以取到其最新值。
写回Cache:得到数据的最新值会困难一些,因为最新值可能在某个Cache中,也可能在主存中。
)
我们就考虑难的!(简单的也不出题)
有时候,还有多出来一个发送的消息:Invalidate消息,用来通知其他各处理器作废其Cache中相应的副本。
(这个和WriteMiss是有区别的,WriteMiss是写不命中,然后回去调取对应的块,但是这个无效化不会)
下面我们先确定好一些概念:
概念;
Cache的标识(tag)可直接用来实现监听。
作废一个块只需将其有效位置为无效。
给每个Cache块增设一个共享位:为“1”:多个处理器所共享,为“0”:某个处理器所独占
块的拥有者:拥有该数据块的唯一副本的处理器。
每个节点内部会有一个有限状态的控制器;
无效(简称I):Cache中该块的内容为无效。
共享(简称S):该块可能处于共享状态。(要求共享的块的内容都要相同)
已修改(简称M):该块已经被修改过,并且还没写入存储器。(要确保这个独占,全系统唯一)
所以我们现在来总体的考虑具体的情况*******;
I:请求来自处理器:(发送)
(
处理器可能会:读命中,读不命中,写命中,写不命中,
但是最后发出去的消息只可能是:读写不命中和Invalidate
cache可能是IMS,三个状态之一
)
(注意这里都是针对的块)
1:什么时候读命中?
要不cache对应的块是S要不就是M,如果是I的话就是读不命中了
(表格,状态机,图例如下)
2:什么时候读不命中
我们的cache块是失效I的,我们需要把读不命中放在总线去
我们的cache块虽然是S,但是地址不对,我们也需要把读不命中放在总线
我们的cache块虽然是M,但是地址不对,我要先写回这个块,然后再去把读不命中放总线
对于第一种情况,读入的就是共享的数据了(不管是来自其他的cache还是存储器),所以I->S,这里的S强调一致性,cache和存储的一致性
第二种得到数据后也是share,只是对应的地址块不同了
第三种会把M->S,然后回显写回块,然后再去替换
3:什么时候写命中?
如果是I,那就是写不命中了,因为这个数据块无效的,不会发生写命中
如果是S,将其修改为M,然后发出I消息,作废这个块上的其他版本(命中==地址是对的)
如果是M,我们会把自然的写入数据(不会写回存储器,因为最新版本都在他自己身上)
4:什么时候写不命中?
如果我们对应的块是I,可能是不命中了,发出写不命中的消息,尝试让别人提供给他目标的块,然后去写入
如果对应的块是S,但是不是对应的地址,把写不命中放在总线上,尝试让别人去提供目标块,然后去写入对应的位置
如果对应的块是M,但是地址不对应,就会先写回这里的地址,然后把写不命中发出,让别人给他这个目标快,然后去写入
(在这可以思考下,如果是S的其他处理器收到了对应块位置的写不命中消息,会干甚?是不是地址不对了,对应记录的数据就无效了?让我们接下来看看)
II:请求来自总线(接收)
(
总线会发来:两个不命中和Invalidate3个信息
我们的caceh状态可能是IMS3个中的一个
)
1:收到读不命中怎么办?
先想想什么时候别人的cache会发送读不命中,是不是IMS都有可能!
想想什么时候我们的cache会收到影响?什么时候我们会去响应这个信号!!我们有对应的数据(SM),尝试去共享!!!
如果我们是I或者是和我们的地址不对应,肯定不会响应的,因为我干不了什么事情
如果我们是匹配的S,我们就是不是可能尝试去共享这个数据给发送者(也可能对方更快的找到了存储器,因为数据是一致的)!!!
如果我们是匹配的M,我们是不是也会尝试去共享,但是注意!!!!!!共享之后我们的状态还是独占吗?不是了,所以要先写回数据,并且中止他对存储器的访问,因为存储器的数据错误!!!!!然后去共享数据,把M->S
2 : 什么时候会收到写不命中??
首先,对方写不命中,之后肯定会写入到cache中,并做一个独占是吧,所以为什么我们会响应这个写不命中尼?是不是就是要去写的就是我们现在拥有的那个,所以我们可能是SM
首先,可能是地址匹配我才会去管是吧,然后如果本来就是I就不用管,其他的S,M都要变成I
(但是由于设计的原因,发送方需要把数据得到后再去写入,所以这里的S可以尝试共享,M就要同时提供给发送发和存储器)
为什么要这么设计???
因为我们的cache里面是存的是cache块,里面不是一个数据,是一堆数据,只是里面的部分数据修改了,所以不能够发送方直接拿着自己的块就开始写,显然是不对的,所以需要拿到整个块(包括修改部分的相邻数据),然后再去写里面对应的地方
3:什么时候会收到失效?
肯定是有处理器尝试去写入共享块,才会发出一个信息让共享块失效,所以我们回一下,是不是只有写命中的S会发出这个信号!!!!(写命中的M不会发出,反正都是他自己独占)
那么对应的,会收到影响的是不是也就只是对应地址的S状态!!!!
(M收不到,因为如果一个块呗独占了,外面不会发生命中)
好了,这样的话,我们就算是梳理完成了
整理一下
相应(接收)请求的状态机
(开始回忆,什么时候收到失效?我们做出了什么状态的变化?什么时候收到读不命中?我们会做出什么变化?什么时候回收到写不命中?我们的那些状态改变了?中间我们做了哪些事情?)
发出请求的时候的状态机:
(我们有哪4种情况?会发出哪3个消息,每个不同的情况我们会做什么?什么时候读命中?针对我们自己那些状态会改变?什么时候读不命中?我们的那些状态会改变?什么时候回写命中?我们的那些状态会改变?什么时候写不命中?我们的状态会发生什么改变?
)
发生替换时:
如果发生替换的话:
总结一下问题:
1:并发问题,因为这个都是假定的每个操作具有原子性,但是实际不是的,可能会有死锁,竞争,可以通过发送Invalidate的cpu占用总线来解决
2:一个块一开始不在cache中,读取的时候会变成share(他是唯一的缓存副本,但是还是会按照多个版本的去处理)
进一步的优化:加入一个状态表示数据是干净的 or owned