Cache 的基本思想

Cache(高速缓冲存储器)的核心思想是:将 CPU 近期可能使用的数据保存在 Cache 中,减少对主存的访问次数。

当 CPU 需要读取数据 A 时:

  • 若 A 已在 Cache 中,直接从 Cache 读取。
  • 若 A 不在 Cache 中,从主存读取,并将对应数据块装入 Cache,方便后续使用。

局部性原理

Cache 能够提高效率,是因为程序访问数据具有局部性。

局部性 含义 例子
时间局部性 最近访问的数据,很可能再次被访问 循环中反复使用变量 sum
空间局部性 访问某地址后,很可能访问附近地址 顺序遍历数组 a[0]、a[1]、a[2]

因此,Cache 利用程序的访问规律,尽量保存 CPU 可能再次使用的数据。

按块存储

Cache 以块(Cache Block,也叫缓存行 Cache Line)为单位存储数据;主存与 Cache 之间也按块传送数据。

例如,若每块为 16 字节,CPU 访问主存地址 100 时,会将包含该地址的整个 16 字节块装入 Cache,而不是只装入所需的一个字节。这样,后续访问相邻地址时,就可能直接命中 Cache。

Cache 的访问流程

典型的 Cache 访问流程:命中时从 Cache 取数;缺失时从主存取块、向 CPU 送数并将块装入 Cache。

图中的 MM 表示 CPU 给出的主存地址。

命中(Hit)

命中是指 CPU 所需的数据已经在 Cache 中。

  1. CPU 发出访存地址。
  2. Cache 检查是否存在对应的有效数据块。
  3. 若存在,从 Cache 读取所需数据并送给 CPU。

例如,CPU 要读取变量 A,而 Cache 中已有 A,就不需要再访问主存。命中时访问速度快。

未命中(Miss,也称缺失)

未命中是指 CPU 所需的数据不在 Cache 中。

  1. CPU 发出访存地址,Cache 检查后发现没有对应的有效数据块。
  2. 从主存读取包含目标数据的块。
  3. 按照缓存策略确定该主存块在 Cache 中的存放位置;若没有可用的空闲块,则需要替换原有缓存块。
  4. 将 CPU 所需的数据送给 CPU,并将主存块装入 Cache。

未命中时需要访问主存,因此耗时更长。图中的两个分支分别表示向 CPU 送数和向 Cache 装块。

命中率与平均访问时间

命中率与缺失率

命中率是 Cache 命中次数占总访存次数的比例:

H=NcN\boxed{H=\frac{N_c}{N}}

其中,HH 为命中率,NcN_c 为 Cache 命中次数,NN 为总访存次数。

缺失率(未命中率)为:

M=1−HM=1-H

这里的 MM 表示缺失率,与流程图中的主存地址 MM 含义不同。

平均访问时间

采用以下简化计时模型:

符号 含义
TcT_c 命中时间,即访问 Cache 所需的时间
TmT_m 缺失损失,即未命中时从主存调入一个块所需的额外时间
TaT_a Cache—主存系统的平均访问时间
  • 命中时:直接从 Cache 取数,耗时为 TcT_c。
  • 未命中时:检查 Cache 后,还需从主存调入数据块,总耗时为 Tc+TmT_c+T_m。

因此,平均访问时间为:

Ta=HTc+(1−H)(Tm+Tc)=Tc+(1−H)Tm\begin{aligned} T_a &= H T_c+(1-H)(T_m+T_c) \\ &= \boxed{T_c+(1-H)T_m} \end{aligned}

重点:平均访问时间 = 命中时间 + 缺失率 × 缺失损失。这里的 TmT_m 是未命中时的额外耗时,未命中的总耗时为 Tc+TmT_c+T_m。