计算机系统-存储器层次结构

本篇不是学习课程时的笔记,是重看这本书时的简记。对于学习本课程的同学,未涉及的内容不代表考试不涉及,部分省略的部分是在该课程的讨论课中学习的(存储器山,矩阵乘法),对于核心内容的掌握,需要学习相关实例和习题(缓存查找)。


计算机系统-存储器层次结构

计算机系统-存储器层次结构_第1张图片

1.存储技术

本部分主要介绍各种存储技术(SRAM,DRAM,ROM,磁盘及读写,固态硬盘),从这些技术中可总结的重要的思想为:

  • 不同的存储技术有不同的价格和性能折中
  • 从不同存储器的价格和性能变化速率不同
  • 增加密度比降低访问时间更容易

2.局部性

一个编写良好的程序应该具有良好的局部性,有两类局部性:

  • 时间局部性:一个被引用的存储器位置很可能很快被再次引用
  • 空间局部性:如果一个存储器位置被引用了,则其相邻的位置很可能很快被引用

体现在程序中,一个变量经常被访问,则符合时间局部性;连续的数据以合适的步长访问,符合空间局部性。(例如多维数组按行访问,按序取指令)

3.存储器层次结构

层次结构

计算机系统-存储器层次结构_第2张图片

存储器层次结构设计的核心思想在于:每层的较快、较小存储作为位于下层的更大、更慢的存储的缓存。

由于局部性,程序更倾向于访问高层次的数据;而下层的存储存取更慢,空间更大,价格便宜。通过这样的存储器层次结构设计,实现了大容量存储+低价格+高速访存。

缓存基本概念

数据在不同的存储层次之间以的形式传输,按块排列在存储器中。不同层次之间的块大小可能不同。越上层块越小,例如L1和L2之间只有8-16个字。

计算机系统-存储器层次结构_第3张图片

在访问存储器K+1时,优先访问高层次的存储K+1,如果要找的数据对象在K层存在,就称为缓存命中。以更快的速度读取到了K+1层的数据。如果K层没有要找的数据,则缓存不命中。不命中的类型有三种:

  • 冷不命中:最开始时,K层存储器为空,一定会不命中,但是这个不命中只会短暂出现
  • 冲突不命中:由于K层存储比K+1层更小,K+1层的多个块映射到K层的同一个位置,这样即使缓存足够大,连续访问映射到一个位置的多个块也会导致不命中
  • 容量不命中:访问的块的集合(称之为工作集)大小超出缓存大小,导致不命中

不同的层次结构之间要传输数据,必须要有逻辑对缓存进行管理。对于L1、L2、L3这样的高速缓存,是由硬件逻辑管理的,下层的主存作为磁盘的缓存,是由操作系统软件和地址翻译硬件共同管理的。

4.高速缓存存储器

在考虑存储层次和缓存时,通常从四个问题考虑:

  • 缓存组织
  • 缓存查找
  • 缓存替换
  • 缓存读与写入策略

缓存组织

缓存组织的方式有三种:

  • 全相联:K+1层的一块可以放到K层的任意一个位置。空间利用率高,冲突概率低,实现复杂
  • 直接映射:K+1层的一块只能放到K层的一个指定位置。空间利用率低,冲突概率高,实现简单
  • 组相联:K+1层的一块可以放到K层的一些位置(一组当中),是全相联和直接映射的折中

下图中K+1层为主存,K层为Cache:

计算机系统-存储器层次结构_第4张图片

实际上全相联映射和直接映射可以看作是特殊的组相联映射。

缓存查找

缓存组织的三种方式都最终归结为组相联,由此可以得出缓存的通用结构:

计算机系统-存储器层次结构_第5张图片

缓存由多个构成,每一组中有多,每一行中有数据块和用于找到该块的信息,以及一个标记位表示该缓存数据是否有效。

如果要从缓存查找到一个数据,必须要有组索引,行标记,和数据在块中的偏移。在组内的查找使用逐个查找的方式,所以没有使用行索引,而是使用标记(Tag)来匹配。由此可以将地址划分为:

计算机系统-存储器层次结构_第6张图片

地址被划分为t、s、b位的三部分,分别用于标记,组索引,偏移。根据这三部分的位数,可以有 2 s 2^s 2s个组, 2 b 2^b 2b个字节数据,最多 2 t 2^t 2t行,但是缓存往往没有这么多行,因此规定每组有E行。据此,缓存的大小为:
C a c h e   S i z e = S × E × B   ( b y t e s ) Cache\ Size = S\times E \times B \ (bytes) Cache Size=S×E×B (bytes)
而缓存查找的过程,只需要从地址中分离出行标记,组索引,块偏移,然后按照先查找组,再匹配行,最后检查有效位并根据偏移取出数据的顺序工作就可以完成。

|补充:组索引的位置

在上面划分地址时,第一步应该是得到组索引,却没有使用高位作为组索引,而是高位作为标记,中间位作为组索引。这样做的原因是避免冲突不命中。我们假设现在只有四个组,每组有一行,用这个情况说明为什么不用高位做组索引的原理:

假设按顺序循环访问数据块0000、0001、0010、0011,如果用高位作组索引,则这四块会映射到同一组,在循环中会反复发生冲突不命中,如果用低位作组索引,这四块会被映射到四个组中,在循环访问时,只有第一次循环的冷不命中。因此采用变化更快的低位为组索引能够一定程度的避免冲突不命中。由于地址低位在各层次及虚拟存储中都默认为偏移量,采用中间位作为组索引。这个问题的核心是用变化比较快的位作为组索引,可以尽量让临近的数据分布到不同的组,避免冲突不命中。

缓存替换

访问一个块不命中时,要把K+1层的块复制到K层,这样下次就可以更快的存取该块。如果K层缓存已满,就要替换掉一块数据,常用的策略有:

  • 随机替换
  • FIFO
  • LRU
  • LFU

实际常用的策略是LRU和LFU,替换后的命中率较高。不过需要记录访问块最近是否访问过。

|补充:抖动现象

对于直接映射缓存,常出现冲突不命中,称为抖动现象。例如假设A[0]和A[1]都映射到同一个位置,循环访问A[0]和A[1],每一次都是不命中的,这种现象称为抖动。

FIFO策略也是导致这种现象的原因之一,假设有缓存有10个数据块大小,而循环访问11个数据块,FIFO策略会导致每一次都是不命中,在这10个块之间抖动。

缓存读写策略

对于读缓存,策略很简单,如果K层没有需要的数据,就从K+1层读取数据到K层(可能需要替换出一些块)。写策略要复杂一些,因为K和K+1层的块都要更新。写有两种策略:

  • 直写:将数据写入K和K+1
  • 写回:将数据写入K,当K中该块要被替换了,才写入K+1

写回能减少数据流量,但是缓存必须维护块是否被修改过的信息(添加修改位)。通常低层次的缓存都采用写回,因为低层次之间的数据传输更慢。

如果写入时发生了不命中,则有两种处理策略:

  • 写分配:将K+1层的数据读到K层,写入
  • 非写分配:直接写入K+1层

一般来说,直写高速缓存是非写分配的,写回高速缓存是写分配的。

缓存的性能评价与参数影响

上面已经讨论了四个高速缓存的问题,接下来分析高速缓存的性能评价和参数影响。

由于不命中对性能的影响很大,性能评价指标以不命中情况为主:

  • 不命中率:不命中数量/引用数量
  • 不命中处罚:不命中导致从K+1层取数据的时间

影响高速缓存性能主要是以下几个方面:

  • 高速缓存大小:大的缓存命中率高,但速度可能会慢
  • 块大小:大块空间局部性要好,但对于给定缓存大小,大块会使行数减少,增加冲突不命中,影响时间局部性,大块的不命中处罚也更大
  • 相联度:即组中的行数E,E较大则复杂性更高,匹配时间更长,但可以减少抖动
  • 写策略

5.高速缓存对性能的影响

本部分主要了解存储器山的概念,矩阵乘法。

你可能感兴趣的:(计算机系统,计算机系统)