静态存储器存储原理
结构
特点
- 速度快
- 存储密度低,单位面积存储容量小
- 数据入/出共用管脚
- 能耗高
- 成本高
高速缓冲存储器(Cache)概述
利用局部性原理
使用高速缓冲存储器 Cache 来提高 CPU 对存储器的平均访问速度。
时间局部性:
- 最近被访问的信息很可能还要被访问。
- 将最近被访问的信息项装入到 Cache 中。
空间局部性:
- 最近被访问的信息临近的信息也可能被访问。
- 将最近被访问的信息项临近的信息一起装入到 Cache 中。
参数
- 块(Line):数据交换的最小单位
- 命中(Hit):在较高层次中发现要访问的内容
- 命中率(Hit Rate):命中次数/访问次数
- 命中时间:访问在较高层次中数据的时间
- 缺失(Miss):需要在较低层次中访问块
- 缺失率(Miss Rate):1-命中率
- 缺失损失(Miss Penalty):替换较高层次数据块的时间 + 将该块交付给处理器的时间
- 命中时间<<缺失损失
- 平均访问时间=HR * 命中时间 + (1-HR) * 缺失损失
参数典型数值
- 块大小:4~128 Bytes
- 命中时间:1~4 周期
- 失效损失:
- 访问时间:6~10 个周期
- 传输时间:2~22 个周期
- 命中率:80%~99%
- Cache 容量:1KB~256KB
要解决的问题
-
地址和 Cache 行之间的映射关系:
- 如何根据主存地址得到 Cache 中的数据?
-
数据之间一致性:
- Cache 中的内容是否已经是主存对应地址的内容?
-
数据交换的粒度:
- Cache 中的内容与主存内容以多大的粒度交换?
-
Cache 内容装入和替换策略
- 如何提高 Cache 的命中率?
Cache 的地址映射
直接映射
特点
- 主存的字块只可以和固定的 Cache 字块对应,方式直接,利用率低。
- 标志位较短,比较电路的成本低。 如果主存空间有 2^m 块,Cache 中字块有 2^c 块,则标志位只要有 m-c 位。且 仅需要比较一次。
- 利用率低,命中率低,效率较低
多路组相联
特点:
- 前两种方式的折衷方案。组内为全相连,组间为直接映射。
- 集中了两个方式的优点。成本也不太高。
- 是常用的方式
全相联
特点:
- 主存的字块可以和 Cache 的任何字块对应,利用率高,方式灵活。
- 标志位较长,比较电路的成本太高。如果主存空间有 2^m 块,则标志位要有 m 位。同时,如果 Cache 有 n 块,则需要有 n 个比较电路。 使用成本太高
一致性保证
写回策略
写直达(Write through)
-
强一致性保证,效率低
-
在 Cache 中命中:同时修改 Cache 和对应的主存内容
-
没有在 Cache 中命中:
- 写分配(Write allocate)
- 非写分配(not Write allocate )
-
拖后写(Write back)
- 弱一致性保证,替换时再写主存
- 主动替换
- 被动替换
- 通过监听总线上的访问操作来实现
- 实现复杂,效率比较高
- 弱一致性保证,替换时再写主存
多核 cache 一致性保证策略 MESI
要保证本地 cache 的数据,其它核 cache 的数据,内存的数据有一个一致的视图
- 修改态(M):处于这个状态的 cache 块中的数据已经被修改过,和主存中对应的数据已不同,只能从 cache 中读到正确的数据
- 独占态(E):处于本状态的 cache 块的数据和主存中对应的数据块内容相同,而且在其它 cache 中没有副本
- 共享态(S):处于本状态的 cache 块的数据和主存中对应的数据块内容相同,而且可能在其它 cache 中有该块的副本
- 无效态(I):处于本状态的 cache 块中尚未装入数据
提高存储访问的性能
平均访问时间 = 命中时间 x 命中率 + 缺失损失 x 缺失率
- 提高命中率
- 缩短缺失时的访问时间
- 提高 Cache 本身的速度
Cache 缺失的原因
- 必然缺失(Compulsory Miss)
- 开机或者是进程切换(冷启动,需要热身)
- 首次访问数据块
- 容量缺失(Capacity Miss)
- 活动数据集超出了 Cache 的大小
- 冲突缺失(Conflict Miss)
- 多个内存块映射到同一 Cache 块
- 某一 Cache 组块已满,但空闲的 Cache 块在其他组
- 无效缺失
- 其他进程修改了主存数据
对策:
- 必然缺失
- 世事总有缺憾
- 如果程序访问存储器的次数足够多,也就可以忽略了(程序先热个身)
- 策略 —— 预取
- 容量缺失
- 出现在 Cache 容量太小的时候
- 增加 Cache 容量,可缓解缺失现象
- 冲突缺失
- 两块不同的内存块映射到相同的 Cache 块
- 对直接映射的 Cache,这个问题尤其突出
- 增加 Cache 容量有助于缓解冲突
- 增加相联的路数有助于缓解冲突
影响命中率的因素
- Cache 容量
- 大容量可以提高命中率,但是贵
- Cache 块大小
- 选择多大的行,还真是个问题
- 地址映射方式
- 多路组相联,但到底多少路呢?
- 替换算法
- 替换哪行出去呢?
- 多级 Cache
- 给用户更多的选择
- 一般来说,数据块较大可以更好地利用空间局部性,
- 但是:
- 数据块大意味着缺失损失的增大:需要花费更长的时间来装入数据块
- 若块大小相对 Cache 总容量来说太大的话,命中率将降低:Cache 块数太少
替换策略
直接映射
- 主存中的一块只能映射到 Cache 中唯一的一个位置
- 定位时,不需要选择,只需替换
全相联映射
- 主存中的一块可以映射到 Cache 中任何一个位置
N 路组相联映射
- 主存中的一块可以选择映射到 Cache 中 N 个位置
全相联映射和 N 路组相联映射的失效处理
- 从主存中取出新块
- 为了腾出 Cache 空间,需要替换出一个 Cache 块
- 不唯一,则需要选择应替出哪块
- 最近最少使用 LRU
- 满足程序局部性要求
- 有较高命中率
- 硬件实现复杂
- 先进先出 FIFO
- 满足时间局部性
- 实现比较简单
- 随机替换 RAND
- 实现简单
- 命中率也不太低
- 最近最少使用 LRU
多级 cache
采用两级或更多级 cache 来提高命中率
- 增加 Cache 层次
- 增加了用户的选择
- 将 Cache 分解为指令 Cache 和数据 Cache
- 指令流水的现实要求(缓解结构冲突)
- 根据具体情况,选用不同的组织方式、容量