写在前面的话:此系列文章为笔者学习CSAPP时的个人笔记,分享出来与大家学习交流,目录大体与《深入理解计算机系统》书本一致。因是初次预习时写的笔记,在复习回看时发现部分内容存在一些小问题,因时间紧张来不及再次整理总结,希望读者理解。
《深入理解计算机系统(CSAPP)》第3章 程序的机器级表示 - 学习笔记_友人帐_的博客-CSDN博客
《深入理解计算机系统(CSAPP)》第5章 优化程序性能 - 学习笔记_友人帐_的博客-CSDN博客
《深入理解计算机系统(CSAPP)》第6章 存储器层次结构 - 学习笔记_友人帐_的博客-CSDN博客
《深入理解计算机系统(CSAPP)》第7章 链接- 学习笔记_友人帐_的博客-CSDN博客
《深入理解计算机系统(CSAPP)》第8章 异常控制流 - 学习笔记_友人帐_的博客-CSDN博客
《深入理解计算机系统(CSAPP)》第9章虚拟内存 - 学习笔记_友人帐_的博客-CSDN博客
第六章 存储器层次结构
1. 随机访问存储器(Random-Access Memory, RAM)
RAM封装在芯片上,基本存储单位是一个单元(celI),每单元存储1比特,多个RAM芯片一起组成一个存储器。
DRAM和SRAM是易失性存储器,断电数据丢失。
1.1 静态RAM(SRAM)
贵 -> cache
SRAM用来作为高速缓存存储器,既可以在CPU芯片上,也可以在片下。
1.2 动态RAM(DRAM)
便宜 -> 内存条
DRAM用来作为主存以及图形系统的帧缓冲区。
2. 非易失性存储器
断电后依然保持数据
- 只读存储器(ROM):生产时写入程序,只能写一次
- 可编程ROM(PROM):可以重新编程一次
- 可擦除PROM(EPROM):可用紫外线整块擦除电
- 可擦除PROM(EEPROM):可用电子信号整块擦除
- 闪存:基于EEPROM,以块为单位进行擦除
应用:
-
存储固件程序的ROM(BIOS,磁盘控制器,网卡,图形加速器,安全子系统,…)
-
固态硬盘(U盘,智能手机,mp3播放器,平板电脑,笔记本电脑…)
-
磁盘高速缓存
3. 连接CPU与存储器的典型总线结构
一条总线(BUS)是由多条并排的电线组成的一束线,其传输地址、数据和控制信号,多个设备共享多条总线。
4. 磁盘
从磁盘上读信息的时间为毫秒级,比从DRAM读慢了10万倍,比从SRAM读慢了100万倍。
4.1 磁盘构造
磁盘是由盘片(platter)构成的。每个盘片有两面(surface),表面覆盖着磁性记录材料。
每面由一组称为**磁道(track)**的同心圆组成。
每个磁道划分为一组扇区(sector),扇区之间由**间隙(gap)**隔开
4.2 磁盘容量
(1)决定因素
- 记录密度(Recording density)(位/英寸):磁道一英寸的段中可放入的bit位数。
- 磁道密度(Track density)(道/英寸):从盘片中心出发半径上一英寸的段内可以有的磁道数
- 面密度(Areal density)(位/平方英寸):记录密度与磁道密度的乘积
(2)分区记录
现代磁盘将所有磁道划分为若干分组(recording zone),组内各磁道相邻。区域内各磁道的扇区数目相同,扇区数取决于区域内最内侧磁道的圆周长。各区域的每磁道扇区数都不同,外圈区域的每磁道扇区数比内圈区域多,所以我们使用每磁道平均扇区数来计算磁盘容量。
(3)容量计算
磁盘容量
=
每个磁盘的盘片数
×
每个盘片的盘面数
×
每个盘面的磁道数
×
平均每个磁道的扇区数
×
每个扇区的字节数
磁盘容量=每个磁盘的盘片数\times 每个盘片的盘面数\times 每个盘面的磁道数\times 平均每个磁道的扇区数\times 每个扇区的字节数
磁盘容量=每个磁盘的盘片数×每个盘片的盘面数×每个盘面的磁道数×平均每个磁道的扇区数×每个扇区的字节数
注意:
1
G
B
=
1
0
9
字节
1GB=10^9字节
1GB=109字节,
1
T
B
=
1
0
12
字节
1TB=10^{12}字节
1TB=1012字节,
4.3 访问时间
磁盘以扇区大小的块来读写数据。
访问时间 = 寻道时间 + 平均旋转延迟 + 数据传输时间
(1)寻道时间
为了读取某个目标扇区的内容,传动臂首先将读/写头定位到包含目标扇区的磁道上。移动传动臂所需的时间称为寻道时间。
寻道时间依赖于读/写头以前的位置和传动臂在盘面上移动的速度。
(2)旋转时间
一旦读/写头定位到了期望的磁道,驱动器等待目标扇区的第一个位旋转到读/写头下。这个步骤的性能依赖于当读/写头到达目标扇区时盘面的位置以及磁盘的旋转速度。在最坏的情况下,读/写头刚刚错过了目标扇区,必须等待磁盘转一整圈。
因此,最大旋转延迟(以秒为单位)是 T m a x r o t a t i o n = 1 R P M × 60 s 1 m i n T_{max rotation}=\frac{1}{RPM}\times \frac{60s}{1min} Tmaxrotation=RPM1×1min60s,也即转一圈所需要的时间。
平均旋转延迟是最大旋转延迟的一半。
(3)传送时间
当读目标扇区所用时间。
一个扇区以秒为单位的平均传送时间为: T a v g t r a n s f e r = 1 R P M × 1 平均扇区数 / 磁道 × 60 s 1 m i n T_{avgtransfer}=\frac{1}{RPM}\times \frac{1}{平均扇区数/磁道}\times \frac{60s}{1min} Tavgtransfer=RPM1×平均扇区数/磁道1×1min60s
访问一个磁盘扇区中字节的时间主要是寻道时间和旋转延迟。访问扇区中的第一个字节用了很长时间,但是访问剩下的字节几乎不用时间。
因为寻道时间和旋转延迟大致相等,所以将寻道时间乘2是估计磁盘访问时间的简单而合理的方法。
4.4 逻辑磁盘块
现代磁盘以简单的抽象视图来表示复杂的磁盘构造,磁盘被抽象成b个扇区大小的逻辑块(logical block)序列(编号为0,1,2,…)。
由磁盘控制器维护逻辑块与物理扇区之间的映射关系。操作系统会发送一个命令到磁盘控制器,让它读某个逻辑块号。控制器上的固件执行一个快速表查找,将一个逻辑块号翻译成一个(盘面,磁道,扇区)的三元组,这个三元组唯一地标识了对应的物理扇区。控制器上的硬件会解释这个三元组。
允许磁盘控制器为每个分区预留一组柱面作为备份。
格式化包括用标识扇区的信息填写扇区之间的间隙,标识出表面有故障的柱面并且不使用它们,以及在每个区中预留出一组柱面作为备用,故“格式化容量”比“最大容量”要小。
5. 固态硬盘SSD
固态硬盘(Solid State Disk,SSD)是一种基于闪存的存储技术
一个闪存由B个块的序列组成,每个块由P页组成。
通常,页的大小是512字节4KB,块的大小为16KB512KB,由32~128页组成。
数据是以页为单位读写的。只有在一页所属的块整个被擦除之后,才能写这一页(通常是指该块中的所有位都被设置为1)。不过,一旦一个块被擦除了,块中每一个页都可以不需要再进行擦除就写一次。
随机写比较慢
-
擦除块需要相对较长的时间(~1ms)
-
如果写操作试图修改一个包含已经有数据(也就是不是全为1)的页p,那么这个块中所有带有用数据的页都必须被复制到一个新(擦除过的)块,然后才能进行对页p的写。
6. 局部性
**局部性原理:**一个局部性良好的程序倾向于引用邻近于其他最近引用过的数据项的数据项,或者最近引用过的数据项本身。
- 时间局部性:最近访问过的信息,很可能在近期还会被再次访问
- 空间局部性:地址接近的数据项,被使用的时间也倾向于接近
7. 存储器层次结构
**存储器层次结构的基本思想:**位于k层的更快更小存储设备作为位于k+1层的更大更慢存储设备的缓存。
- 因为局部性原理,程序访问第k层的数据比访问第k+1层的数据要频繁
- 第k+1层的存储设备更慢、容量更大、价格更便宜
8. 高速缓存cache
高速缓存(Cache):将一种更小、速度更快的存储设备,作为更大、更慢存储设备的缓存区。
8.1 基本的缓存原理
-
各层存储器被划分成连续的数据对象组块(chunk),称为块(block)。每个块都有一个唯一的地址或名字。
-
相邻层次之间的块的大小是相同的。第k层的缓存包含第k+1层块的一个子集的副本。
-
不同层次对之间块的大小可以不同。
-
数据以块大小为传送单元(transfer unit)在第k层和第k+1层之间来回复制。
8.2 缓存命中
(1)缓存命中
当程序需要第k+1层的某个数据对象d时,它首先在当前存储在第k层的一个块中查找d。如果d刚好缓存在第k层中,那么就是缓存命中(cache hit)。
(2)缓存不命中
如果当前层的缓存中没有想要的数据,那么就是缓存不命中(cache miss)。
当发生缓存不命中时,第k层的缓存从第k+1层缓存中取出包含d的那个块,如果第k层的缓存已经满了,可能就会覆盖现存的一个块。
替换策略:决定该替换存储器中的哪一块
随机替换策略
最近最少被使用替换策略
放置策略:决定块b放在缓存中的位置
缓存不命中的种类:
-
冷不命中
当缓存为空时,对任何数据的请求都会不命中(例如刚开机)。
-
冲突不命中
大部分缓存将第k+1层的某个块限制在第k层块的一个子集里(有时只是一个块)。例如,第k+1层的块i必须放置在第k层的块(i mod 4)中。当缓存足够大,但是被引用的对象都映射到同一缓存块中,此种不命中称为冲突不命中。
-
容量不命中
当工作集(working set)的大小超过缓存的大小时,会发生容量不命中。
9. 高速缓存寄存器
高速缓存存储器是小型的、快速的基于SRAM的存储器,是在硬件中自动管理的,保存经常访问主存的块。
常见的L1、L2、L3三级缓存。
9.1 通用的高速缓存存储器组织结构(S, E, B)
高速缓存的结构可以用元组(S,E,B)描述。
一共有S组,每组有E行,每行中地址有m位。
而地址的格式为:
后b位为块偏移,然后是s位的组索引,其余全部为标记位。
高速缓存读
- 定位组
- 定位行:检查集合中是否有匹配标记的行,且行有效 -> 命中
- 定位数据:从块偏移开始的数据读,如果是int型就读4字节……
9.2 分类
(1)直接映射高速缓存(E=1)
特点:每一组只有一行
(2)全相联映射(S=1)
特点:仅有一个组,主存中任何一块都可以映射到cache中的任何一块。
(3)组相联映射(E>1, S>1)
二者的折中
9.3 关于写
缓存内容存在于多个副本:L1,L2,L3,主存,磁盘
写中时:
- 直写:立即写入存储器
- 写回:推迟到缓存行要替换时才写入内存(但需要一个修改位来标识缓存行与内存是否相同/有修改)
写不命中时:
- 写分配:加载到缓存,更新这个缓存行。如后续有较多向该位置的写,优势明显。
- 非写分配:直接写到主存中,不加载到缓存中
典型方案:①直写+非写分配 ②写回+写分配
9.4 性能指标
(1)不命中率
不命中率
=
不命中次数
访问次数
=
1
−
命中率
不命中率 = \frac{不命中次数}{访问次数} = 1-命中率
不命中率=访问次数不命中次数=1−命中率
(L1 3~10%;L2 <1%)
**(2)**命中时间
从高速缓存向处理器发送一行的时间,包括判断行是否在缓存中
(L1 4个时钟周期;L2 10个时钟周期)
(3)不命中除法
由于不命中需要额外的时间,通常主存需50-200周期(趋势:增加!)
9.5 编写高速缓存友好的代码
专注在核心函数和内循环上。
使用内层循环的缓存不命中数量降到最低
- 反复引用变量好(时间局部性)
- 步长为1的引用模式好(空间局部性)
9.6 重新排列以提高空间局部性
9.7 使用块来提高时间局部性
聚焦内层循环:大部分计算和内存访问都发生在这里。
最大化空间局部性:以1为步长,按数据在内存中的存储顺序读取。
最大化程序时间局部性:从内存中读入一个数据对象后,尽可能频繁/多地使用它。