购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

3.4 内存一致性协议

在过去的30年间,CPU的发展非常快,运行的速度呈指数级提升。而DRAM的发展速度缓慢,内存的读取速度一直处于缓慢提升的状态,如图3-10所示。

图3-10 CPU与DRAM发展速度

CPU与DRAM的运行速度之间出现了非常大的鸿沟,为了弥补两者之间的性能差异,让CPU的性能能够充分发挥出来,硬件工程师们在CPU中引入了高速缓存。

在现代化设计的CPU上,高速缓存存储器分为三个部分:一级缓存(L1 Cache)、二级缓存(L2 Cache)和3级缓存(L3 Cache),每个CPU都有一个独立一级缓存和二级缓存。三级缓存是由所有CPU内核共用的。CPU缓存的逻辑架构如图3-11所示。

图3-11 CPU缓存逻辑架构

一级缓存可以分为一级指令缓存(L1i)和一级数据缓存(L1d),分别用来存储指令和数据。一级缓存是与CPU结合最为紧密的CPU缓存,也是历史上最早出现的CPU缓存。由于一级缓存的技术难度和制造成本都非常高,提高容量所带来的技术难度和成本都非常大,所有一级缓存的容量一般都比较小、通常在32~512KB。

二级缓存是CPU的二级缓存,介于一级缓存与三级缓存之间。二级缓存的容量也会影响CPU的性能,理论上是越大越好,但受制于技术与成本的压力一般也不会特别大,通常在2~16MB之间。

三级缓存是为读取二级缓存后未命中的数据设计的一种缓存,在拥有三级缓存的CPU中,只有约5%的数据需要从内存中调用,这进一步提高了CPU的效率。三级缓存的容量一般都比较大,可以达到几十MB。

3.4.1 CPU缓存读取策略

当CPU试图读取数据的时候,首先从一级缓存中查询是否命中,如果命中则把数据返回给CPU。如果一级缓存数据缺失,则继续从二级缓存中查找。如果二级缓存数据缺失,则继续从三级缓存中查找。如果三级缓存数据缺失,则从主内存中查找。

在查找数据的时候,数据该存储在哪个级别的缓存是由缓存策略决定的。缓存策略总体上有两种:Inclusive Policy Cache(较高级别的缓存包含较低级别的缓存),以及Exclusive Policy Cache(较高级别的缓存不包含较低级别的缓存)。

1.Inclusive Policy Cache

为了方便演示,图3-12是以两级CPU缓存结构为例来演示数据读取的策略,其中L2(二级缓存)和L1(一级缓存)是包含关系。

图3-12 Inclusive Policy Cache缓存策略

如图3-12所示,最初L1和L2都是空的。

步骤1 :处理器发送一个读取X的请求。一开始L1和L2都没有数据的,因此从主存加载数据填充到L1和L2,如图3-12b所示。

步骤2 :处理器发送读取Y的请求,该请求在L1和L2都没有数据。因此从主存加载数Y,Y被填充到L1和L2中,如图3-12c所示。

步骤3 :把X从L1中移除,那么它只会从L1中移除,如图3-12d所示。

步骤4 :接着把Y从L2中移除,它会向L1发送invalidation请求,L1也会把Y移除,如图3-12e所示。

2.Exclusive Policy Cache

为了方便,图3-13是以两级CPU缓存结构为例来演示Exclusive Policy Cache策略,其中L2和L1是不包含关系。

图3-13 Exclusive Policy Cache策略

如图3-13所示,最初L1和L2都是空的,如图3-12a所示。

步骤1 :处理器发送一个读取X的请求。发现在L1和L2中都没有数据,因此需要从主存获取并填充到L1,如图3-12b所示。

步骤2 :处理器再次发出读取Y的请求,该请求在L1和L2中都没有数据。因此需要从主存获取并填充到L1中,如图3-12c所示。

步骤3 :如果X必须从L1中逐出,那么它会从L1中移除,填充到L2中,如图3-12d所示。

3.4.2 CPU缓存写入策略

当CPU要修改缓存中的数据,CPU的缓存又是如何与主内存进行同步的呢?接下来讲解CPU缓存的两种写策略:写直达(Write Through)和写回(Write Back)。

当CPU执行store指令并在缓存命中时,缓存与主存中的数据会被更新。缓存和主存的数据始终保持一致。写直达策略在对L1 Cache数据进行修改的时候会同时修改L2 Cache。当CPU执行store指令并在缓存命中时,只更新缓存中的数据。另外,每个缓存行中会有一个位(bit)记录数据是否被修改过,称之为dirty bit。当数据更新时会将dirty bit设置为1。在采用写回策略时,CPU在对L1 Cache数据进行修改时不会修改L2 Cache中的数据。主存中的数据只会在缓存行被替换或者显式的clean操作时更新。因此主存中的数据可能不是最新的数据,L1 Cache、L2 Cache和主存的数据可能不一致。

写直达能够保证实时的一致性,但每次数据的修改需要同步到CPU缓存与主内存,整个运行的效率比较慢。写回(Write Back)虽然在数据一致性上有一些延迟,但整个运行效率得到极大提升。

3.4.3 MESI协议

MESI协议是基于Invalidate的高速缓存一致性协议,并且是支持写回缓存数据更新策略的最常用协议之一。MESI是Midified(已修改)、Exclusive(独占)、Shared(共享)、Invalidated(已失效)的缩写,对应缓存行的4种状态。

1) 修改 :高速缓存行仅存在于当前高速缓存中,并且是刚修改过的,也就是“脏”的,它需要把修改的数据从CPU缓存中同步到主内存。在允许其他CPU对整个数据读取之前,需要把高速缓存的数据写回内存。回写将该行更改为共享状态(S)。

2) 独占 :缓存行只仅存在于当前CPU缓存中,表示数据被当前CPU独占(E)。如果其他CPU缓存也存储了该数据,就会将其更改为共享状态。如果当前CPU对数据进行修改,就会将其变为修改状态。

3) 共享 :表示此数据在多个CPU缓存中,数据被多个CPU所共享,并且没有任何一个CPU对这个数据进行修改。

4) 无效 :表示此缓存行为无效。当块标记为M(已修改)时,其他高速缓存中块的副本将标记为I(无效)。

图3-14是一个简单的例子,用来阐述数据在CPU缓存中的状态变迁过程。

图3-14 CPU缓存数据状态变迁

步骤1 :内存中有个变量V,储值为0,然后CPU0读取变量V,V只在CPU0的缓存中,相当于被CPU0独占了,所以状态是E。

步骤2 :CPU1也读取了变量V,这个时候变量V会存储在两个CPU缓存中,就相当于处于共享状态S。

步骤3 :CPU0对本地缓存变量V进行了修改,将其修改成了1,并将数据的状态改成M,之后广播一条数据已经被修改的消息。CPU1收到消息,将本地缓存中的V修改成失效状态I。

步骤4 :CUP1再次读取变量V,CPU缓存中的数据已经失效,需要重新从内存中读取数据。而这个时候数据总线发现这个变量在CPU0里面是M的状态,会先把数据从CPU0缓存同步到内存中,这个时候内存中数据V的值是1。然后把V读取到CPU1中,并把CPU0、CPU1中的数据状态都改成S。

CPU缓存处于CPU与内存之间,一方面需要响应本CPU的读、写请求,另一方面需要响应缓存总线发送过来的其他CPU的数据读写请求。本CPU请求主要分为读请求与写请求,详细说明如表3-3所示。

表3-3 缓存读/写请求

缓存总线不仅会转发其他CPU的数据读写要求,还包括需要当前缓存与主内容同步的请求,详细信息如表3-4所示。

表3-4 缓存请求指令

Cache在面对CPU读写操作的请求会做出响应,详细信息如表3-5所示。

表3-5 缓存对CPU操作的响应

(续)

缓存在面对内存总线操作请求时会做出响应,详细信息如表3-6所示。

表3-6 缓存对总线操作的响应 PN8vkcoNzd8kSsqgJB1Npa9Gy6t+uGHvVtuaLExhJm7QEZinL8fZ7U8qY7XX1LqY

点击中间区域
呼出菜单
上一章
目录
下一章
×