第九讲 高速缓冲存储器 Cache
Cache的基本思路
解决内存墙带来的CPU和主存协作问题
- 在使用主存(相对大而慢)之余,添加一块小而快的cache
- Cache位于CPU和主存之间,可以集成在CPU内部或作为主板上的一个模块
- Cache中存放了主存中的部分信息的“副本”
Cache的工作流程
- Check当CPU试图访问主存中的某个字时,首先检查这个字是否在cache中
检查后有两种情况
- 命中(Hit):如果在cache中,则把这个字传送给CPU
- 未命中(Miss):如果不在cache中, 则将主存中包含这个字固定大小的块(block)读入cache中,然后再从cache传送该字给CPU
如何判断命中还是未命中: 使用标记
标记就是物理地址 - 块内偏移量 - cache组索引部分
tag + 组索引 + 块内偏移量, 这样tag + 组索引也就是块号部分
如果未命中, 为什么不直接把所需要的字从内存传送到CPU?: 利用程序访问的时间局部性
如果未命中,为什么从内存中读入一个块而不只读入一个字?: 利用程序访问的空间局部性
程序访问的局部性原理
- 时间局部性: 在相对较短的时间周期内,重复访问特定的信息
- 空间局部性: 在相对较短的时间周期内,访问相邻存储位置的数据
使用Cache后需要更多的操作,为什么还可以节省时间?
计算Cache的平均访问时间
假设p是命中率, Tc是访问Cache的时间, Tm是访问主存的时间T = p * Tc + (1-p) * (Tc + Tm) = Tc +(1-p)Tm
Tc越小, p越大 Cache的效果越好
如果想要T < Tm, 则必须有 p > Tc/Tm
Cache的构成
Cache是由SRAM构成的
- 标记存储体tag SRAM :存放主存的组号
- 数据存储体Cache SRAM:存放组内对应块的主存信息
Cache的设计要素
- 容量
- 增大容量可以提高命中率, 但也增大了访问Cache时间
- 映射功能
- 直接映射
- 关联映射
- 组关联映射
- 替换算法
- 直接映射没有替换算法
- 最近最少使用算法LRU:替换掉在cache中最长时间未被访问的数据块
- 先进先出算法FIFO:替换掉在Cache中停留时间最长的块
- 最不经常使用算法LFU:替换掉cache中被访问次数最少的数据块
- 随机替换算法:随机替换cache中的数据块
- 写策略
- 当cache中的某个数据块被替换时,需要考虑该数据块是否被修改
- 写直达:所有写操作都同时对cache和主存进行
- 写回法:先更新cache中的数据,当cache中某个数据块被替换时,如果它被修改了,才被写回主存
- 行大小
- 一行(也就是一块)有多少字节
- 和命中率的关系较为复杂
- Cache数目
- 一级和多级Cache
- 统一和分立的Cache
- 分立Cache分为存数据的Cache和存指令的Cache
不同映射功能
- 直接映射
- 优点: 简单, 快速检查, 快速映射
- 缺点: 抖动现象, 如果一个程序重复访问两个需要映射到同一行中且来自不同块的字,则这两个块不断地被交换到cache中,cache的命中率将会降低
- 适合大容量Cache
- 关联映射
- 优点: 避免抖动, 因为一个块能装入Cache中任意一行
- 缺点: 实现起来比较复杂, Cache搜索代价很大,即在检查的时候需要去访问cache的每一行
- 适合小容量Cache
- 组关联映射 (K-路组关联映射)
- 结合了直接映射和关联映射的优缺点
- 面向不同容量的cache做了折中
- 关联度越低,命中率越低
- 直接映射的命中率最低,关联映射的命中率最高
- 关联度越低,判断是否命中的时间越短
- 直接映射的命中时间最短,关联映射的命中时间最长
- 关联度越低,标记所占额外空间开销越小
- 直接映射的标记最短,关联映射的标记最长