跳转到内容

5. Memory Hierarchy

硬盘、内存、CPU 寄存器,还有本节要讲的 Cache,这些都是存储器,计算机为什么要有这么多种存储器呢?这些存储器各自有什么特点?这是本节要讨论的问题。

由于硬件技术的限制,我们可以制造出容量很小但很快的存储器,也可以制造出容量很大但很慢的存储器,但不可能两边的好处都占着,不可能制造出访问速度又快容量又大的存储器。因此,现代计算机都把存储器分成若干级,称为 Memory Hierarchy,按照离 CPU 由近到远的顺序依次是 CPU 寄存器、Cache、内存、硬盘,越靠近 CPU 的存储器容量越小但访问速度越快,下图给出了各种存储器的容量和访问速度的典型值。

图 17.8. Memory Hierarchy

Memory Hierarchy

表 17.1. Memory Hierarchy

存储器类型位于哪里存储容量半导体工艺访问时间如何访问
CPU 寄存器位于 CPU 执行单元中。CPU 寄存器通常只有几个到几十个,每个寄存器的容量取决于 CPU 的字长,所以一共只有几十到几百字节。“寄存器”这个名字就是一种数字电路的名字,它由一组触发器(Flip-flop)组成,每个触发器保存一个 Bit 的数据,可以做存取和移位等操作。计算机掉电时寄存器中保存的数据会丢失。寄存器是访问速度最快的存储器,典型的访问时间是几纳秒。使用哪个寄存器,如何使用寄存器,这些都是由指令决定的。
Cache和 MMU 一样位于 CPU 核中。Cache 通常分为几级,最典型的是如上图所示的两级 Cache,一级 Cache 更靠近 CPU 执行单元,二级 Cache 更靠近物理内存,通常一级 Cache 有几十到几百 KB,二级 Cache 有几百 KB 到几 MB。Cache 和内存都是由 RAM(Random Access Memory)组成的,可以根据地址随机访问,计算机掉电时 RAM 中保存的数据会丢失。不同的是,Cache 通常由 SRAM(Static RAM,静态 RAM)组成,而内存通常由 DRAM(Dynamic RAM,动态 RAM)组成。DRAM 电路比 SRAM 简单,存储容量可以做得更大,但 DRAM 的访问速度比 SRAM 慢。典型的访问时间是几十纳秒。Cache 缓存最近访问过的内存数据,由于 Cache 的访问速度是内存的几十倍,所以有效利用 Cache 可以大大提高计算机的整体性能。一级 Cache 是这样工作的:CPU 执行单元要访问内存时首先发出 VA,Cache 利用 VA 查找相应的数据有没有被缓存,如果 Cache 中有就不需要访问物理内存了,如果是读操作就直接将 Cache 中的数据传给 CPU 寄存器,如果是写操作就直接改写到 Cache 中;如果 Cache 没有缓存该数据,就去物理内存中取数据,但并不是要哪个字节就取哪个字节,而是把相邻的几十个字节都取上来缓存着,以备下次用到,这称为一个 Cache Line,典型的 Cache Line 大小是 32~256 字节。如果计算机还配置了二级缓存,则在访问物理内存之前先用 PA 去二级缓存中查找。一级缓存是用 VA 寻址的,二级缓存是用 PA 寻址的,这是它们的区别。Cache 所做的工作是由硬件自动完成的,而不是像寄存器一样由指令决定先做什么后做什么。
内存位于 CPU 外的芯片,与 CPU 通过地址和数据总线相连。典型的存储容量是几百 MB 到几 GB。由 DRAM 组成,详见上面关于 Cache 的说明。典型的访问时间是几百纳秒。内存是通过地址来访问的,在启用 MMU 的情况下,程序指令中的地址是 VA,而访问内存用的是 PA,它们之间的映射关系由操作系统维护。
硬盘位于设备总线上,并不直接和 CPU 相连,CPU 通过设备总线的控制器访问硬盘。典型的存储容量是几百 GB 到几 TB。硬盘由磁性介质和磁头组成,访问硬盘时存在机械运动,磁头要移动,磁性介质要旋转,机械运动的速度很难提高到电子的速度,所以访问速度很受限制。保存在硬盘上的数据掉电后不会丢失。典型的访问时间是几毫秒,是寄存器访问时间的 106 倍。由驱动程序操作设备总线控制器去访问。由于硬盘的访问速度较慢,操作系统通常一次从硬盘上读几个页面到内存中缓存起来,如果这几个页面后来都被程序访问到了,那么这一次读硬盘的时间就可以分摊(Amortize)给程序的多次访问了。

对这个表格总结如下。

  • 寄存器、Cache 和内存中的数据都是掉电丢失的,这称为易失性存储器(Volatile Memory),与之相对的,硬盘是一种非易失性存储器(Non-volatile Memory)。
  • 除了访问寄存器由程序指令直接控制之外,访问其它存储器都不是由指令直接控制的,有些是硬件自动完成的,有些是操作系统配合硬件完成的。
  • Cache 从内存取数据时会预取一个 Cache Line 缓存起来,操作系统从硬盘读数据时会预读几个页面缓存起来,都是希望这些数据以后会被程序访问到。大多数程序的行为都具有局部性(Locality)的特点:它们会花费大量的时间反复执行一小段代码(例如循环),或者反复访问一个很小的地址范围中的数据(例如访问一个数组)。所以预读缓存的办法是很有效的:CPU 取一条指令,我把和它相邻的指令也都缓存起来,CPU 很可能马上就会取到;CPU 访问一个数据,我把和它相邻的数据也都缓存起来,CPU 很可能马上就会访问到。设想有两台计算机,一台有 256KB 的 Cache,另一台没有 Cache,两台计算机的内存都是 512MB 的,硬盘都是 100GB 的,虽然多出来 256KB 的 Cache 与内存、硬盘的容量相比微不足道,但访问 Cache 比访问内存、硬盘快几个数量级,由于局部性原理,CPU 大部分时间是在和 Cache 打交道,有 Cache 的计算机明显会快很多。高速存储器的容量只能做得很小,却能显著提升计算机的性能,这就是 Memory Hierarchy 的意义所在。