CPU多级缓存: 缓存一致性、乱序执行优化

CPU多级缓存

cpu多级缓存
当前我们看到的这个图,展示的最简单的高速缓存的配置,数据的读取和存储都经过高速缓存,cpu核心与高速缓存之间有一条特殊的快速通道,在这个简化的图中,主存与高速缓存都连接在一条系统总线上,这条总线同时还用于其他组件的通信。
cpu多级缓存
在高速缓存出现后不久,系统变得更加复杂,高速缓存与主存之间的速度差距变得更大,直到加入另一级的缓存,新加入的缓存比第一缓存更大,但是更慢,由于加大一级缓存从经济利益上看是行不通的,所以有了二级缓存,甚至现在的有些系统拥有三级缓存。

我们为什么需要CPU缓存呢?

CPU的频率太快了,快到主存跟不上,这样在处理器时钟周期内,CPU常常需要等待主存,浪费资源。所以缓存的出现,是为了缓解CPU和内存之间速度的不匹配问题。(结构:cpu --> cache --> memory)

CPU缓存有什么意义?

首先,缓存的容量远远小于主存,因此出现缓存不命中的情况在所难免。既然缓存不能包含CPU所需要的所有数据,那么缓存的存在真的有意义吗?
当然它是有意义的,

1. 时间局部性: 如果某个数据被访问,那么在不久的将来它很有可能再次被访问。

2. 空间局部性: 如果某个数据被访问,那么与它相邻的数据很快也可能被访问。

CPU多级缓存 - 缓存一致性(MESI)

缓存一致性是一个协议,同于保证多个CPU cache之间缓存共享数据的一致

MESI定义了四种状态,也就是CPU对四种操作产生不一致的状态。缓存控制器监听到本地操作和远程操作的时候,需要对cache做出修改,从而保证数据在多个缓存中的一致性。
MESI四种状态
MESI其实是四种状态的缩写。
M: modified(被修改)。该缓存行只被缓存在CPU的缓存中,并且是被修改过的,因此它与主存中的数据是不一致的,该缓存行的内存需要在未来的某个时间点写回主存,这个时间点是允许其他CPU读取主存相应的内存之前。当这里的值被写回主存后,该缓存行的状态会变成E(exclusive)状态。

E: exclusive(独享)。该缓存行只被缓存在该CPU缓存中,是未被修改过的,与主存中数据一致的。这个状态可以在任何时刻,当有其他CPU读取该缓存行时,变成S(shared)状态。当CPU修改该缓存行内容时,该状态可以变成M(modified)状态.

S: shared(共享)。该缓存行可能被多个CPU缓存,并且各个缓存的数据和主存的数据一致,当有一个CPU修改该缓存行的时候,其他CPU从该缓存行是可以被作废的,变成I(invalid)状态。

I: invalid(无效的)。这个缓存是无效的,可能是其他CPU修改了该缓存。

四种操作:
Local read: 读本地缓存中的数据
Local write: 将数据写入本地的缓存中
Remote read: 将内存的数据读取过来
Remote write: 将数据写回到主存中

状态转换
MESI该协议的数据状态有四种,引起数据状态转换的CPU cache操作也有四种,因此要完整的理解MESI这个协议,本质上是要将这16种状态转换的情况讨论清楚

在一个有多核的系统中,每一个核都有自己的缓存来共享主存总线,每个CPU回发出读写请求,而缓存的目的是为了减少CPU读写共享主存的次数。
一个缓存除了在I(invalid)状态之外都可以满足CPU的读请求。
一个写请求只有在M(modified)或者E(exclusive)状态下才能执行,如果处在S状态,必须先将缓存中该缓存行变成I状态。通常通过广播方式执行。这个时候不允许多个CPU修改同一个缓存行,即使修改该缓存行不同位置的数据也是不允许的。
一个处于M(modified)状态的缓存行,必须监听所有试图读缓存行的操作,这种操作必须在缓存将缓存行写回到主存,并将状态变回S状态之前被延迟执行。
一个处于S(shared)状态的缓存行,也必须监听其他缓存使该缓存行无效或者独享该缓存行的请求并将缓存行变成无效。
一个处于E(exclusive)状态的缓存行,要监听其他缓存读缓存中该缓存行的操作,一旦有该缓存行的操作,它就会变成S(shared)状态。
因此,对于M和E两种状态而言,他们的数据总是精确的,和缓存行的真正状态是一致的,S状态可能是非一致的,如果一个缓存将处于S状态的缓存行作废,另一个缓存实际上可能已经独享了该缓存行,但是该缓存却不会将缓存行升为E状态,这是因为其他缓存不会广播它们作废掉该缓存行的通知。同样,由于缓存并没有保存该缓存行的copy的数量,因此也没办法确定自己是否已经独享了该缓存行。
从上面的话来看,E更像一个投机性的优化,因为一个CPU想修改一个S状态的缓存行,总线事务需要将所有该缓存行copy的值变成I状态,但修改E状态的缓存,却不需要总线事务。

CPU多级缓存 - 乱序执行优化

什么是乱序执行优化呢?
处理器为了提高运算速度而做出违背代码原有顺序的优化。

我们举个例子:例子1
这里就有两种执行顺序:
正常状态下,先将a赋值为10,再将b赋值为200,最后计算a*b赋值给result。
cpu乱序执行优化后,有可能先将b赋值为200,再将a赋值为10,最后再计算result。
例子结果
在单核单线程中,是不会对结果造成影响的。但是在多核或者多线程情况下就有可能会出现问题。

首先,在多核情况下,同时会有多个核执行指令,每个指令都有可能被乱序,另外,处理器还引入了L1、L2等缓存机制,每个核都有自己的缓存,这就导致了逻辑次序上,后写入内存的数据未必真的最后写入,最后会带来一个问题,如果我们不做任何防护措施,处理器最后得出的结果会和我们逻辑得出的结果大不相同。

比如、我们在一个核上执行数据写入操作,然后在操作最后写一个标记来表示之前的数据已经准备好了,然后我们从另外一个核上通过判断这个标记,来判断需要的数据是否已经就绪。那如果考虑到上面说的乱序执行优化,这种做法就存在一定风险,比如标记先被写入,但是之前的操作还未完成,这个未完成可能是没有计算完成,也可能是数据没有从处理器缓存中刷新到主存当中,这就导致了另外一个核使用到了错误的数据。

这就是数据不安全,也就是说在并发情况下,一定要保证线程安全。

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值