(二)并发编程的基础

2-1 CPU 多级缓存-缓存一致性

(二)并发编程的基础_第1张图片
带有高速缓存的CPU执行计算的流程
1.程序以及数据被加载到主内存
2.指令和数据被加载到CPU的高速缓存
3.CPU执行指令,把结果写到高速缓存
4.高速缓存中的数据写回主内存

为什么要用CPU高速缓存cache?
CPU的频率很快,在处理器时钟周期内,CPU常常要等待主存,浪费资源,cache的出现缓解了CPU和内存之间的速度不匹配。

cache的意义
时间局部性,如果某个数据被访问,那么在不久的将来它很可能被再次访问。
空间局部性:如果某个数据被访问,那么与它相邻的数据很快也可能被访问。

重点和难点**:CPU多级缓存一致性协议MESI**
用于保证多个CPU cache之间缓存共享数据的一致,即多核CPU的情况下有多个一级缓存,如何保证缓存内部数据的一致,不让系统数据混乱。这里就引出了一个一致性的协议MESI。

MESI 是指4中状态的首字母。每个Cache line有4个状态,可用2个bit表示,它们分别是:

缓存行(Cache line):缓存存储数据的单元。

状态 描述 监听任务
M 修改 (Modified) 该Cache line有效,数据被修改了,和内存中的数据不一致,数据只存在于本Cache中。 缓存行必须时刻监听所有试图读该缓存行相对就主存的操作,这种操作必须在缓存将该缓存行写回主存并将状态变成S(共享)状态之前被延迟执行。
E 独享、互斥 (Exclusive) 该Cache line有效,数据和内存中的数据一致,数据只存在于本Cache中。 缓存行也必须监听其它缓存读主存中该缓存行的操作,一旦有这种操作,该缓存行需要变成S(共享)状态。
S 共享 (Shared) 该Cache line有效,数据和内存中的数据一致,数据存在于很多Cache中。 缓存行也必须监听其它缓存使该缓存行无效或者独享该缓存行的请求,并将该缓存行变成无效(Invalid)。
无效 (Invalid) 该Cache line无效。

M和E的数据都是本core独有的,不同之处是M状态的数据是dirty(和内存中的不一致),E状态的数据是clean(和内存中的一致)
S状态是所有Core的数据都是共享的,只有clean的数据才能被多个core共享
I表示这个Cache line无效

注意:

对于M和E状态而言总是精确的,他们在和该缓存行的真正状态是一致的,而S状态可能是非一致的。如果一个
缓存将处于S状态的缓存行作废了,而另一个缓存实际上可能已经独享了该缓存行,但是该缓存却不会将该缓
存行升迁为E状态,这是因为其它缓存不会广播他们作废掉该缓存行的通知,同样由于缓存并没有保存该缓存
行的copy的数量,因此(即使有这种通知)也没有办法确定自己是否已经独享了该缓存行。

从上面的意义看来E状态是一种投机性的优化:如果一个CPU想修改一个处于S状态的缓存行,总线事务需要将
所有该缓存行的copy变成invalid状态,而修改E状态的缓存不需要使用总线事务。


在MESI协议中,每个Cache的Cache控制器不仅知道自己的读写操作,而且也监听(snoop)其它Cache的读
写操作。每个Cache line所处的状态根据本核和其它核的读写操作在4个状态间进行迁移。

MESI协议状态迁移图如下
(二)并发编程的基础_第2张图片
在上图中,Local Read表示本内核读本Cache中的值,Local Write表示本内核写本Cache中的值,Remote Read表示其它内核读其它Cache中的值,Remote Write表示其它内核写其它Cache中的值,箭头表示本Cache line状态的迁移,环形箭头表示状态不变。
当内核需要访问的数据不在本Cache中,而其它Cache有这份数据的备份时,本Cache既可以从内存中导入数据,也可以从其它Cache中导入数据,不同的处理器会有不同的选择。MESI协议为了使自己更加通用,没有定义这些细节,只定义了状态之间的迁移,下面的描述假设本Cache从内存中导入数据。

当前状态 事件 行为 下一个状态
I(Invalid) Local Read 如果其它Cache没有这份数据,本Cache从内存中取数据,Cache line状态变成E;如果其它Cache有这份数据,且状态为M,则将数据更新到内存,本Cache再从内存中取数据,2个Cache 的Cache line状态都变成S;如果其它Cache有这份数据,且状态为S或者E,本Cache从内存中取数据,这些Cache 的Cache line状态都变成S E/S
I(Invalid) Local Write 从内存中取数据,在Cache中修改,状态变成M;如果其它Cache有这份数据,且状态为M,则要先将数据更新到内存;如果其它Cache有这份数据,则其它Cache的Cache line状态变成I M
I(Invalid) Remote Read 既然是Invalid,别的核的操作与它无关 I
I(Invalid) Remote Write 既然是Invalid,别的核的操作与它无关 I
E(Exclusive) Local Read 从Cache中取数据,状态不变 E
E(Exclusive) Local Write 修改Cache中的数据,状态变成M M
E(Exclusive) Remote Read 数据和其它核共用,状态变成了S S
E(Exclusive) Remote Write 数据被修改,本Cache line不能再使用,状态变成I I
S(Shared) Local Read 从Cache中取数据,状态不变 S
S(Shared) Local Write 修改Cache中的数据,状态变成M,其它核共享的Cache line状态变成I M
S(Shared) Remote Read 状态不变 S
S(Shared) Remote Write 数据被修改,本Cache line不能再使用,状态变成I I
M(Modified) Local Read 从Cache中取数据,状态不变 M
M(Modified) Local Write 修改Cache中的数据,状态不变 M
M(Modified) Remote Read 这行数据被写到内存中,使其它核能使用到最新的数据,状态变成S S
M(Modified) Remote Write 这行数据被写到内存中,使其它核能使用到最新的数据,由于其它核会修改这行数据,状态变成I I

你可能感兴趣的:(JAVA并发编程)