通信模式
共享存储
统一的地址空间,每一个处理器都可以访问。但是需要注意并发控制。
使用线程。
消息传递
使用单独的地址
共享存储系统
因为性能原因,使用多个私有缓存
当一个chip读取一个值时,必须读取到最近写入的值。
缓存一致性(Cache Coherence):执行一个读操作,应该返回哪一个值。
存储一致性(Memory Consistency):如何让一个写操作让所有人都看到。
缓存一致性(Cache Coherence)
cache1中是2,但是之后cache3中写入了值3。
处理器核3若读取到2,那么读到了一个旧值,应当读到most recent值3.
一致性协议
写传播:保证一个写最终让所有处理器看到。
写序列:一堆写操作应当能够序列化。
如何保证写传播
写无效协议:在执行一个写操作时,将其他所有的副本无效。
写更新协议:在执行写操作后,更新所有副本
如何观测共享状态并序列化请求
基于侦听:所有cache通过共享总线观察其他cache的动作。
基于目录:多处理器维持一个目录,目录会跟踪所有私有缓存内容,然后进行排序。
基于侦听
由总线确保序列化。
-
-
-
- 广播模式,确保所有有序。
- 每一个缓存控制器侦听所有总线事务。
- 控制器更新缓存的状态。
- 使用写传播策略。
-
-
基于侦听序列化请求——VI协议(Valid/Invalid)
VI协议四种动作
处理器读:处理器自己的缓存中load一个值。
处理器写:处理器会写入一个值到cache。(会触发总线写,写入主存,同时让其他cache都无效)
总线读:触发总线读的处理器,从主存load一个值到自己的cache
总线写:发出总线写的处理器,将自己的cache写入到主存。其他处理器收到总线写消息,将自己的cache设置为Invalid
VI协议两种状态
Valid:缓存数据有效,可以直接读。
Invalid:缓存数据无效,只能从主存读,触发总线读,加载数据到cache。
VI协议的缺陷
每一次写都要更新主存。(因为处理器写会触发总线写)
每次写都需要广播。
状态变换图
Valid -> Valid : 处理器读(读一个valid的cache),处理器写,总线写。
Valid -> Invalid:响应总线上的总线写。
Invalid -> Valid: 处理器读,总线读
Invalid-> Invalid:处理器写,总线写
实线是响应处理器的动作,虚线是响应总线的动作。
core0 load一个值0xA,但是缓存中没有,触发总线读,从主存load一个值到cache.
core0 store值3到缓存,触发总线写,,将cache更新到主存,同时使得其他core的cache变为Invalid。
core1 load缓存中的值时,发现缓存中的值为Invalid,于是触发总线读,将主存的值load到cache中
特点
读取
if cache.state=='Invalid' :
总线读,从主存读,且从load一个值到cache。
else :
直接读取缓存。
写入
总线写,将自己cache值写入到主存。
让其他core的cache变为无效
基于侦听序列化请求——MSI协议
三种状态
Modified:当前Cache已修改,缓存中数据与主存数据不一致(会触发总线排他读,其他cache变为无效,有效且修改过)
Shared:表示当前的处理器已经从另一个被Modified的处理器中获取到了数据。(有效且是最新的)
Invalid:当前Cache块失效,需要从其他状态为“S”或“M”的CPU出拿数据。
每一个Cache修改了一个数据后,其他Cache会被标记为无效。
五种动作
处理器读:处理器自己的缓存中load一个值。
处理器写:处理器会写入一个值到cache。(会触发总线写,写入主存,同时让其他cache都无效)
总线读:触发总线读的处理器,从主存load一个值到自己的cache
总线写:发出总线写的处理器,将自己的cache写入到主存。其他处理器收到总线写消息,将自己的cache设置为Invalid
总写排他读:触发总线读的处理器,将其他的cache状态变为Invalid,自己状态变为Modify
缺点
收到其他core发出的总线排他读,自己cache变为Invalid,其他某个core的cache中是最新的,但是没写入到主存。
若这时候读取cache,会触发总线读,直接从主存中读取一个值,只存中的值是旧的。
状态变化
Shared -> Modified :向自己的缓存中写入一个值,但是没写入主存,状态变为Modified。
Shared -> Invalid:其它Core将最新的值写入其缓存,触发总线排他读,收到总线排他读表示自己是旧的无法使用,状态变为Invalid。
Invalid -> Modified:向自己的Core写入一个值。
Invalid -> Shared:读取的时候自己是Invalid,于是状态为Modified的cache会将值写会主存,然后自己总线读一个值,这个值就是最新的。
Modified -> Shared:其他cache为Invalid时被读取,自己将cache写入主存以便其他core读取,于是自己的变为最新的,状态为Shared。
后两条的前提读取Invalid时触发的cache miss 能够被识别,否则会导致读取旧的数据。
案例
Core0 load一个值,发现cache中没有数据,于是触发总线读,从主存读取一个值到自己的cache。
Core1 load一个值,发现cache中没有数据,于是触发总线读,从主存读取一个值到自己的cache。
Core0 store一个值10到自己的cache,自己的状态变为Modify,触发总线排他读,其他Core的Cache变为无效。(表示自己是最新的)
core1 store一个值10到自己的cache,自己状态变为Modify,触发总线排他读。其他core的状态变为Invalid。(表示自己的最新的)
core0 load一个值,发现自己的cache状态为Invalid,那么Core1会使用总线写将自己的cache写入主存,然后Core0从主存load一个值到自己cache。(主存中值可能是旧的值,这也是缺点)
特点
写入cache时,仅仅是变为Modify,不写入主存,然后发出总线排他读,并使得其它CPU的cache无效。
但是cache状态为Invalid时若读取,则会读取主存的数据,但是主存中数据可能是旧的。
解决方法
增加一个Exclusive状态:如果没有其他的share,也就是没有最新的未写入到主存的值,一个读取应该变成E状态,且不触发总线读。(用E表示从主存读到最新的)
增加Owner状态:负责写回,相当于S状态+负责写回。
当从M状态到S状态时,其他处于M状态的变成O状态而不是S
切分事务
打破了总线事务的原子性。
可以支持同时多事务执行。
优点
拥有更高的吞吐率。
缺点
但是响应不一定是顺序
基于目录
特点
通过目录路由所有一致事务
非广播,乱序网络
缓存一致性——假共享
产生的原因:缓存一致性是块级别而不是word级别,但是一个块可以有多个word。
P1写wordi,P2写wordk,两个word由相同的块地址。
可能导致冲突,P1写完使得P2写的无效,P2写了后导致P1写的值无效。(Ping-Pong效果。)
缓存一致性——总线占用
一个原子操作read-modify-write需要两个内存操作。而不用其他处理器介入内存操作。
在多处理器环境下,总线在原子读或写操作整个期间被锁住。
LR/SC指令
产生原因
总线事务的总数没必要减少,可以将原子指令切分为LR和SC指令。
Load Reserve
指令格式:lr.{w/d}.{aqrl} rd,(rs1)
作用:读取保留,将rs1中内容加载到rd寄存器,在rs1对应地址上设置保留标记。
Store Conditional
指令格式:sc.{w/d}.{aqrl} rd,rs2,(rs1)。
作用:条件存储,根据条件将值将rs2写入到rs1内,不满足条件则不读。
切分为LR和SC指令的好处:
增加总线利用率。
避免了缓存ping-pong效应。(因为进程只要尝试获取互斥锁,得到了互斥锁才写,而不用每次尝试执行store操作)
标签:缓存,cache,总线,主存,Invalid,处理器,一致性 From: https://www.cnblogs.com/RedNoseBo/p/17308589.html