csapp第六章 存储器层次结构
在简单模型中,存储器系统是一个线性的字节数组,而cpu能够在一个常数时间内访问每个存储器位置。
实际上,存储器系统是一个具有不同容量、成本和访问时间的存储设备的层次结构。
存储器层次结构是可行的。整体效果是一个大的存储器池,其成本与层次结构底层最便宜的存储设备相当,但是却以接近于层次结构顶部存储设备的高速率向程序提供数据。
计算机系统中一个基本而持久的思想:如果你理解了系统是如何将数据在存储器层次结构中上下移动的,那么你就可以编写你的应用程序,使得它们的数据项存储在层次结构较高的地方,在那里cpu能更快的访问它们。
这个思想围绕着计算机程序的一个称为局部性的基本属性。
在本章中,我们会看看基本的存储技术,并描述它们是如何被组织成层次结构的。
6.1 存储技术
随机访问存储器分为两类:静态,动态。SRAM比DRAM更快,更贵。SRAM作为高速缓存存储器。DRAM作为主存。
SRAM将每个位存储在一个双稳态存储单元里。只要有电,它就保持他的值。
DRAM将每个位存储为对一个电容的充电。DRAM单元在10-100ms内失去电荷,所以需要刷新或者其他的方法保证数据正确性。
DRAM表示一般写成N*W,w是一个单元的位数,N是单元数。本身称这个单元是超单元。然后N又表示为r*c,这样的表示是寻址的时候地址引脚不会太多,比如N=16,就要4个引脚。4*4的话,4需要两个引脚。但是这种二维阵列组织有个缺点:两步发送地址,增加了访问时间。
DRAM的增强型有:FPM DRAM,EDO DRAM,SDRAM,DDR SDRAM(DDR,DDR2,DDR3),Random DRAM,VRAM。
PC使用的DRAM历史:95之前FPM,96-99EDO,-02SDRAM和DDR,-10DDR3。
非易失性存储器,SRAM和DRAM都是易失的。
ROM称为只读存储器是历史原因,很多ROM都是可写的。ROM的分类是以它们能够被重编程(写)的次数和对他们进行重编程的机制来划分的。
ROM包括:PROM,EPROM,EEPROM,闪存(基于EEPROM)。
存储在ROM设备中的程序通常称为固件。
总线事物:读事物——从主存传送数据到cpu,写事物——从cpu传送数据到内存。
磁盘是广为应用的保存大量数据的存储设备:盘片,表面,主轴,RPM,磁道,扇区,柱面。
对于SRAM和DRAM,KMGT通常是1024为基,但对于磁盘,KMGT以1000为基。
像图形卡,监视器,鼠标,键盘和磁盘这样的I/O设备,都是通过I/O总线(PCI)连接到cpu和主存的。
系统总线和存储器总线是与cpu总线相关的,但pci这样的总线和底层cpu无关。
I/O总线总是比系统总线和存储器总线慢,但是它可以容纳种类繁多的第三方I/O设备。主机总线适配器将一个或多个磁盘连接到I/O总线,最常用的是SCSI和SATA,前者更贵,更快。
cpu使用一种称为存储器映射I/O的技术,在使用该技术的系统中,地址空间中有一块地址是为与I/O设备通信保留的。每个这样的地址称为一个I/O端口。当一个设备连接到总线上时,它与一个或多个端口相联系。
cpu从磁盘读数据时发生的步骤:cpu通过将命令、逻辑块号和目的存储器地址写到与磁盘相关联的存储器映射地址,发起一个磁盘读;磁盘控制器读扇区,并执行到主存的DMA传送;DMA传送完成时,磁盘控制器用中断的方式通知CPU。
现代磁盘将他们的构造呈现为一个简单的视图,一个B个扇区大小的逻辑块序列。磁盘控制器维护着逻辑块号和实际(物理)磁盘扇区之间的映射关系。这里看到,逻辑块对应扇区。
SSD包,由一个或多个闪存芯片和闪存翻译层组成。
存储器和磁盘技术的一个基本事实:增加密度比降低访问时间更容易。
DRAM和磁盘的性能滞后于cpu的性能。现代计算机频繁的使用基于SRAM的高速缓存,试图弥补处理器-存储器之间的差距。这种方法可行是因为应用程序的局部性。
6.2 局部性
一个编写良好的计算机程序尝尝具有良好的局部性。也就是说,他们倾向于引用临近于其他最近引用过的数据项的数据项,或者最近引用过的数据项本身。
这种倾向性,被称为局部性原理,是一个持久的概念,对硬件和软件系统的设计和性能都有着极大的影响。
局部性通常有两种不同的形式:时间局部性和空间局部性。
两者的区别在于时间对的是一个存储器位置,空间对的是附近的存储器位置。
被引用过一次的存储器位置很可能在不远的将来再被多次引用——时间。一个存储器位置被引用了一次,那么程序很可能在不远的将来引用附近的一个存储器位置——空间。
对于空间局部性,步长为1的引用模式称为顺序引用模式,这种模式具有最好的空间局部性,如数组,一个一个的顺序访问具有最好的空间局部性。
多维数组,按照行优先顺序,具有最好的空间局部性。
量化评价一个程序中局部性的简单原则:
- 重复引用同一个变量的程序有良好的时间局部性。
- 对于具有步长为k的引用模式的程序,步长越小,空间局部性越好。具有步长为1的引用模式的程序有很好的空间局部性。
- 对于取指令来说,循环有好的时间和空间局部性。循环体越小,循环迭代次数越多,局部性越好。
6.3 存储器层次结构
存储器层次结构是组织存储器系统的方法,人想的,现在所有的计算机系统都使用了这种方法。
一般而言,高速缓存是一个小而快速的存储器设备,它作为存储在更大,也更慢的设备中的数据对象的缓冲区域。使用高速缓存的过程称为缓存。
存储器层次结构的中心思想是:对于每个k,位于k层的更快更小的存储设备作为位于k+1层的更大更慢的存储设备的缓存。
也就是说层次结构的每一层都缓存来自较低一层的数据对象。
这里必须强调一下,这也就是说数据时不可以越级的吗?
数据总是以块大小为传送单元在第k层和第k+1层之间来回拷贝的。例子:L1和L0的传送是1个字的块,L2和L1之间是8-16个字的块。
一些概念:缓存命中,缓存不命中,牺牲块,替换策略,冷缓存,强制性不命中,冷不命中,放置策略,冲突不命中,容量不命中。
- 编译器管理寄存器文件,缓存层次结构的最高层。
- L1,L2和L3的缓存完全是由内置在缓存中的硬件逻辑来管理的。
- DRAM主存作为存储在磁盘上的数据块得缓存,是由操作系统和cpu上的地址翻译硬件共同管理的。
- AFS这样的分布式文件系统,本地磁盘作为缓存,它是由运行在本地机器上的AFS客户端进程管理的。
概况来说,基于缓存的存储器层次结构行之有效,是因为较慢的存储设备比较快的存储设备更便宜,同时,还因为程序往往展示局部性。
6.4 高速缓存存储器
早期计算机系统的存储器层次结构只有三层:cpu寄存器,DRAM主存,磁盘。随着cpu和主存之间差距的逐渐增加,系统设计者被迫加入了SRAM高速缓存存储器,称为L1/L2/L3高速缓存。
L1通常需要2-4个时钟周期,L2通常需要10个时钟周期,L3通常需要30-40个时钟周期。
高速缓存存储器结构的一些细节:直接映射高速缓存,组相联高速缓存,全相联高速缓存。
高速缓存参数的性能影响:不命中率,命中率,命中时间,不命中处罚。
(这一节,了解一些硬件知识,结构的细节不管了)
6.5 编写高速缓存友好的代码
局部性比较好的程序更容易有较低的不命中率,而不命中率较低的程序往往比不命中率较高的程序运行的更快。
下面就是我们用来确保代码高速缓存友好的基本方法:
让最常见的情况运行得快。程序通常把大部分时间都花在少量的核心函数上,而这些函数通常把大部分时间都花在了少量循环上。
每个循环内部缓存不命中数量最小。(对局部变量的反复引用是好的,步长为1的引用模式是好的)
6.6 综合:高速缓存对程序性能的影响
存储器系统的性能不是一个数字就能描述的,相反,它是一座时间和空间局部性的山,这座山的上升高度差别可以超过一个数量级。明智的程序员会试图构造他们的程序,使得程序运行在山峰而不是低谷。
还是这几项,推荐的技术:
- 将你的注意力集中在内循环上,大部分计算和存储器访问都发生在这里。
- 通过按照数据对象存储在存储器中的顺序、以步长为1的来读数据,从而使得你程序中的空间局部性最大。
- 一旦从存储器中读入了一个数据对象,就尽可能多的使用它,从而使得程序中的时间局部性最大。
6.7 小结
(over)