这一节是对多层次存储系统中的“Cache-主存”层次的解读。Cache-主存层:主要解决CPU和主存速度不匹配的问题。之间的数据调动是由硬件自动完成的。
Cache常用SRAM(更快、更贵、集成度更低),内存常用DRAM(更慢、更便宜、集成度更高)。
目录
4.1程序访问的局部性原理
对大量典型程序运行情况分析的结果表明,在较短的时间间隔内,程序产生的地址往往集中在存储器的一个很小的范围,这种现象称为程序访问的局部性,包括时间局部性和空间局部性。
时间局部性:被访问的存储单元在较短的时间间隔内可能再次被访问。
空间局部性:被访问的存储单元的邻近单元在较短的时间间隔内很可能被访问。
空间局部性的产生原因是指令在内存中按顺序存放,数据在内存中也可能是数组类型的顺序存放。时间局部性的产生原因是循环程序和子程序通常被连续执行。
4.2 Cache的基本工作原理
Cache通常集成在CPU中,在CPU和主存之间设置Cache,把主存中被频繁访问的地址信息所在块调入Cache,CPU就可以在Cache中更快地访问到这个块内的信息。
考虑到局部性原理,假设我们以内存中64B作为一个块,当访问这个块的某个地址时就把它写入Cache。具体对应关系如下:
主存块大小=cache块大小
Cache的 “块” 也可称 “行”。
关于命中率和缺失率问题主要有两个要点:
- 是否为cache和主存同时访问。
- A[x]=A[x]+32。这个操作涉及读和写操作各一次,计算命中率时需注意。
为了完善这个工作原理,我们有以下三个问题:
- Cache和主存的映射方式(访问了主存的块并把它写入Cache,之后我们怎么在Cache中寻找)
- Cache中主存块的替换算法(如果Cache满了,我们访问内存中的块时又必须写入Cache,该怎么替换?)
- Cache写策略(CPU修改了Cache中的数据副本,如何确保主存中数据母本的一致性)
4.3 Cache和主存的映射方式
- 直接:每个主存块映射到Cache的固定行中。
- 全相联:每个主存块映射到Cache的任意行中。
- 组相联:每个主存块映射到Cache固定组的任意行中。
- 需要给Cache每块设置一个标记来记录Cache对应存储的是哪个内存块。
- 由于cache行的标记位初始为全0,并非存储了内存块中相应位全0的信息,因此为了说明Cache行中的信息是否有效,每个Cache行需要一个有效位。
4.3.1直接映射
主存中的每一个块对应的Cache的唯一位置:
Cache行号 = 主存块号 mod Cache行数。
假设Cache有(黄色)行,主存有(蓝色加黄色)块,只需“标记”的位为 m-c (蓝色)位即可。Cache的块号充当了“部分标记位”的作用。
给定一个内存地址时,如何在Cache中寻找?
只需先访问地址的黄色位找到对应Cache行号,然后当Cache标记位和该内存地址的高位一致且有效,则命中成功。
4.3.2全相联映射
全相联:每个主存块映射到Cache的任意行中。
因此标记位的位数就是主存块号的位数。
4.3.3组相联映射
把Cache分成Q个大小相等的组,组内采用全相联映射(随机)、组间采用直接映射(唯一)
当Q=1时变为全相联映射,当Q=Cache行时变为直接映射。当Q=2时,称为二路组相联。
Cache组号=主存块号 mod Cache组数(Q)
根据这个映射关系,我们给定一个内存地址,那么其内存块地址的后Q位和Cache的行号是对应的,我们的标记位可以不用存储这Q位的信息。
4.3.4小结
直接映射 | 全相联映射 | 组相联映射 | |
---|---|---|---|
命中率 | 最低 | 最高 | 适中 |
判断命中的时间开销 | 最小 | 最大 | 适中 |
4.4 Cache中主存块的替换算法
采用直接映射时,由于每个块只对应一个Cache块,所以直接替换。采用全相联映射时当Cache空间已被占满时我们就要选择替换哪个块的内容,组相联映射是当Cache组内空间不足时就需替换算法,这两者没有本质的不同。
4.4.1随机算法(RAND)
Random,实现简单,但是未考虑局部性原理,会导致Cache命中率低。
4.4.2先进先出算法(FIFO)
First in First out,实现简单,但是也未考虑局部性原理,最早进入的主存块可能是目前经常要使用的。
4.4.3最不经常使用算法(LFU)
Least Frequent used,为每一个块设置一个计数器,用于记录Cache块的访问次数,当需要替换时替换计数器最小的。
这个算法需要的额外空间比较多,同时如果多次使用一个程序但结束后不再使用,它依旧会长时间占用Cache空间。
4.4.4近期最少使用算法(LRU)
Least resent used,为每一个块设置一个计数器,用于记录Cache块多久没有被使用了,当需要替换时替换计数器最大的(即最久没有被使用的Cache块)
计数器的变化规则:
- 命中时,所命中的行的计数器清零,比其低的计数器加1,其余不变;
- 未命中且还有空闲行时,新装入的行的计数器置0,其余全加1;
- 未命中且无空闲行时,计数器最大的行的被替换,新装入的行的计数器置0,其余全加1。
对第1条的解释:我们只需将比“命中的行的计数器”更小的“计数器”加1即可,比“命中的行的计数器”更大的已经确定替换次序。即假设如果有8组数据,我们用三位计数器就可以表示出替换的次序。
当集中访问的存储区超过Cache组的大小时,命中率可以会变的很低,如1,2,3,4,5,1,2,3,4,5,Cache的每组只有4行命中率为0,这种现象称为抖动。
4.5 Cache写策略
4.5.1 全写法(写直通法)
write-through,当CPU对Cache写命中时,必须把数据同时写入主存和Cache。
为减少全写法直接写入主存的时间消耗,在Cache和主存之间加一个写缓存(Write Buffer),CPU同时写数据到Cache和写缓冲中,写缓存再由专门的控制电路将内容写回主存。写缓存可以解决速度不匹配的问题。
但若出现频繁写时,会使写缓存饱和溢出,此时Cache需等待写缓存恢复空间。
4.5.2 回写法
当CPU对Cache写命中时,只把数据写入Cache,而不立即写回主存,只有当此块被换出时才写回主存。
这种方法减少了访存次数,但存在不一致的隐患。为了减少写回主存的开销,每个Cache行设置一个修改位(脏位)来记录替换时需不需要写回主存。
4.5.3 写分配法
4.5.4 非写分配法
4.6 习题
①n路组相联映射时,若总容量不变,将Cache块容量增加一倍,则字块内地址位宽增加,组号位宽减少,标记tag位宽不变(tag=主存-块内位数-组号位数)