存储器之高速缓冲器(Cache)(上篇)

概要

目前CPU遇到以下两个问题:

  1. I/O设备向主存请求时,CPU无法访问主存,只能空等着
  2. 主存速度的提高 始终跟不上 CPU的发展

为了避免CPU和I/O设备争抢方寸,可在CPU与主存之间加一级Cache,此时CPU只需要跟Cache交互即可;另一方面,添加Cache还能解决主存与CPU速度的不匹配。

问题的提出

  1. 为什么添加一个Cache可以解决主存与CPU速度的不匹配问题?
  2. 既然Cache速度这么快,为什么不用 Cache 替换 主存?
  3. Cache的工作原理?
  4. 如何判断Cache的性能?
  5. Cache的性能由哪些方面决定?
  6. CPU、Cache、主存间是如何进行交互的?

为什么添加一个Cache可以解决主存与CPU速度的不匹配问题

因为经过数据分析,发现代码执行时是存在 局部性的。
局部性主要分成两部分:时间局部性空间局部性

  • 时间局部性:CPU从主存取指令或取数据时,在一定时间内,可能会对同个块重复访问。
  • 空间局部性:由于数据在主存内都是连续存放的,所以很可能下一个即将访问的指令也在同一个区域内。

根据以上两点,只要将CPU近期要用到的程序和数据提前存到Cache中,那么CPU在一定时间内,只需要访问Cache即可。

既然Cache速度这么快,为什么不用 Cache 替换 主存

因为Cache一般采用SRAM制作,其价格比主存昂贵。

Cache的工作原理

主存由2n个可编址的字组成,每个字有惟一的n位地址。
为了与Cache映射,将主存与缓存都分成若干 ,每个块内又包含多个 ,并使他们的块大小相同(即块内字数相同)。

这就将主存的地址分成了两端:主存块号块内地址主存块号的位数 + 块内地址的位数 = 一个字的位数

除此之外,Cache中有一个“标记”。标记是用来表示当前存放的是 哪一块主存块。设置这个标记是因为 Cache块 远比 主存块 ,所以Cache里停留的内容不会是固定的,需要一个东西标志 某个缓存块对应的主存块。

不是主存地址可以通过转换获取缓存地址吗,为什么还需要标志位?因为Map需要的时间是最少的。

Cache-主存原理

Cache的性能指标

判断Cache好坏的指标有三个:

  • Cache的命中率
  • Cache的平均访问时间
  • Cache的访问效率

Cache的命中率

Cache命中率 = 命中数 / (命中数 + 未命中数)

当CPU欲访问主存中的某块数据时,Cache中正好存在,则称为 缓存命中
当CPU欲访问主存中的某块数据时,Cache中不存在,则称为 缓存不命中

平均访问时间

平均访问时间 = 命中时访问时间 * 命中率 + (1 - 命中率) * 未命中时间

平均访问时间 越接近 命中时访问时间越好

访问效率

在平均访问时间的基础上,扩充出访问效率,即访问效率 = 平均访问时间 / 命中时访问时间

Cache的性能由哪些方面决定

通常来说,Cache 由 块的数量块的长度决定的。

Cache块的数量

因为Cache的块数量够多,达到主存的块数量,那么Cache除了第一次不命中,后面都是100%命中的。

Cache块的长度

Cache的块长则需要具体情况具体分析,因为Cache块过短,保存的数据量不够多,可以被命中的字少了,那么命中率就下降了;而Cache块过长,缓存中块数减少,可装入的块就少了,很容易出现新块 覆盖 旧块,然后因为新块被使用次数不够多,最终导致命中率下讲;另外块过长,可能会导致一些不相关的数据保存进来,白白浪费空间。

总结

一般来说Cache块通常取4~8个字或字节,也可以取 一个主存周期所能获得的主存信息长度。

CPU、Cache和主存间的交互

CPU、Cache和主存间的交互

Cache存储体

Cache存储体以块为单位与主存交换信息,为了加速主存和Cache之间的调用速度,主存通常采用多体结构,且Cache访存的优先级最高。

主存Cache地址映射变换机构

该机构是将CPU送来的主存地址转换为Cache地址。由于主存和Cache的块内地址都是一样的长度,因此地址映射变换机构主要是将 主存块号 转换成 Cache块号。如果Cache命中,则CPU可以直接访问Cache存储体;如果Cache未命中,CPU会直接访问主存,不仅将该字从主存中取出,同时将它(代指字)所在的主存块一并存入Cache内。如果Cache不可装进,就得采用替换策略;反正,可以直接装入Cache。

替换机构

当Cache内容已满时,需要根据一定的替换算法将Cache内的某个块移除,从而装入新的主存块。

注意:Cache对用户是透明得,用户编程时用到的地址是主存地址,用户根本不知道这些主存是否已调入Cache内。因为将主存块调入Cache的任务全由机器硬件自动完成。

Cache的读写操作

Cache读

Cache读如下图所示
Cache的读操作

当CPU发出主存地址后,先判断该字是否在Cache中。若命中,直接访问Cache,并将该字送至CPU;若未命中,一方面要访问主存,将该字传送给CPU,与此同时,要将该字所在的主存块装入Cache。

Cache写分为 写通回写两种方法

Cache的写直达操作
当CPU对某个Cache块内的数据进行修改时,也将对应的主存块的内容进行修改。

Cache的回写操作
当CPU对某个Cache块内的数据进行修改后,该块被标记为 。当Cache发生替换时,将浊的块写回主存中去。

注意,上述的写操作都只针对于单核处理去,对于多核处理器,需要考虑Cache一致性问题

Cache的改进

改进方法有以下两种:

  • 增加Cache级数
  • 将统一的Cache变成分立的Cache

增加Cache级数

一开始CPU的Cache是直接集成在芯片内部的,这种Cache称为片内Cache(又或是L1 Cache)。片内Cache离CPU近,CPU也不需要占用系统总线就可以直接访问,速度极快。但是片内Cache没有相应数据块时,CPU被迫要访问主存内的信息,访问次数多了,速度相比直接访问Cache就慢下来很多。

所以为了解决CPU与主存间通讯占用总线的问题:在主存与片内缓存之间再加一级缓存,称为 片外缓存片外缓存不使用系统总线而是 使用一个独立的数据路径。那么从片外缓存调入片内缓存的速度就得到了提高。

所以增加一个层次,即 片外Cache,该Cache置于L1与主存之间,当CPU要获取数据,先访问L1 Cache,如果L1 Cache没有,则访问L2 Cache。

将统一的Cache变成分立的Cache

统一缓存是将数据、指令都存放在同一缓存内;分立缓存是将指令和数据分别存放在指令Cache、数据Cache内。

两种方案如何选择是由 存储结构指令控制方式两个方面决定的。

如果存储结构是统一的(指令和数据存储在同一主存内),则相应的Cache采用统一缓存;如果主存采用指令、数据分开存储的方案,则相应的Cache采用分立缓存

如果指令控制方式是超前控制或流水控制,一般采用分立缓存。

超前控制指在当前指令执行过程尚未结束时,就提前将下一条准备执行的指令取出,称为 超前取指指令预取;流水线控制指多条指令同时执行,又可视为指令流水。