并发编程之CPU缓存一致性协议MESI
1、一致性问题的产生
在多核CPU情况下,每个CPU都有自己的一、二级缓存,在多核处理的情况下,如果一方修改了CPU中已经缓存的东西,而又没有通知已经读取到该cache line的另一方,就会导致两边信息不一致。
2、缓存一致性协议MESI
MESI(Modified Exclusive Shared or Invalid)(也成为伊利诺斯协议,是因为该协议由伊利诺斯州立大学提出)是一种广泛使用的支持写回策略的缓存一致性协议。
3、MESI协议中的状态
CPU中每个缓存行(cache line)使用4种状态进行标记(cache line中使用额外的两位(bit)标识)
M:被修改(Modified)
该缓存行被缓存在该CPU中,并且是被修改过的(dirty)(此时其他CPU中该缓存行和主存中该缓存行的状态都是无效的(invalid)),与主存中的数据不一致,该缓存行中的数据需要在未来某个时间点(允许其他CPU读取主存中相应的内容之前)写回(write back)主存。
当被写回主存之后,该缓存行的状态会变成独享(exclusive)状态。
E:独享的(Exclusive)
该缓存行只被缓存在该CPU中,它是未被修改过的,与主存中数据一致。该状态可以在任何时候当有其他CPU读取主存中该缓存行时,变成共享状态(shared)。
S:共享的(Shared)
该状态意味着该缓存行可能被多个CPU缓存,并且各个缓存中的数据与主存数据一致,当有一个CPU修改对应缓存行后,其他CPU中对应的该缓存行被作废(变成无效状态invalid)。
I:无效的(Invalid)
该缓存行是无效的(可能有其他CPU修改了该缓存行),不能被其他CPU读取,并使用,需要修改该cache line对应的CPU写回数据后方可重新访问。
4、MESI状态流转
MESI状态之间的迁移过程如下:
说明:
Local Read:表示本内核读取本cache line的值;
Local Write:表示本内核写本cache line的值;
Remote Read:标识其他内核读取其他cache line的值;
Remote Write:标识其他内核写其他cache line的值。
下图示意了,当一个cache line的调整的状态的时候,另外一个cache line 需要调整的状态。
M | E | S | I | |
---|---|---|---|---|
M | × | × | × | √ |
E | × | × | × | √ |
S | × | × | √ | √ |
I | √ | √ | √ | √ |
举个例子来说:
假设在主存中有cache line,有一个变量m=1,如下图
CPU-A 发出了一条读取指令,从主存中读取m,从主存中通过bus读取到内核缓存,因为当前只有CPU-A拥有该缓存行,且数据状态一致,所以在CPU-A中,该缓存行状态是E,并且主存中的缓存行可以被其他内核读取。
此时CPU-B发出了一条读取指令,从主存中读取m,CPU-B从主存中读取m时,CPU-A监听到了这个操作,此时CPU-A和CPU-B中该缓存行的状态即为S(数据与主存中的状态一致)
假设此时CPU-A对m进行计算,此时CPU-A将缓存行设置成M(修改),并通知CPU-B,CPU-B中此时该缓存行的状态是I(无效状态),并且主存中该缓存行的状态也是无效状态,不能被读取和操作。
CPU-A修改完数据后,CPU-B需要使用最新的数据,CPU-B发出读取指令后,CPU-A在某个时刻将数据写回到主存,在CPU-A中该缓存行状态由M变为S,并且主存中该缓存行数据变为有效,此时CPU-B再去读取一遍,此时CPU-B中该缓存行数据变为S。