?? 共享优质资源 ??
学习路线指南(点击解锁) | 知识定位 | 人群定位 |
---|---|---|
?? Python实战微信订餐小程序 ?? | 进阶级 | 本课程是python flask 从项目建设到腾讯云部署上线,微信小程序的完美结合,打造了全栈订餐系统。 |
??Python量化交易实战 | 入门级 | 携手打造易扩展、更安全、更高效的量化交易系统 |
6 存储层次结构
存储器系统(memory system)是具有不同容量、成本和访问时间的存储设备的层次结构。CPU 最常用的数据常用的数据。靠近 CPU 快速高速缓存储器(cache memory)存储在相对慢速的主存储器中作为一部分(main memory)数据和指令的缓冲区。主存储器暂时存储在大容量和慢速磁盘上的数据,通常作为存储在通过网络连接的其他机器磁盘或磁带上的缓冲区。
具有良好局部性的程序倾向于一次又一次地访问相同的数据项集,或者更倾向于访问相邻的数据项集。
多个具有不同容量、成本和访问时间的存储设备构成,称为。
访问执行指令时数据所需的周期数:
- CPU寄存器:0个周期
- L1L高速缓存:475个周期
- 主存:数百个周期
- 磁盘:数千万个周期
6.1 存储技术
基本的存储技术
- ,分为两类:
-
- ,同时也是,也分为两类:
-
- :静态随机访问存储器,速度快,价格高。主要用作高速缓存存储器。
- :动态随机访问存储器,速度慢,价格低。帧缓冲器主要用作主存和图形系统
- ,同时也是。属于 ROM,基于闪存开发。
- 机械硬盘
- 固态硬盘(SSD)
6.1.1 随机访问存储器
随机访问存储器 (Random-Access Memory, RAM)分为静态和动态两类。SRAM 比 DRAM 更快,但也贵得多。SRAM 可用作高速缓存储器 CPU 芯片上,也可以在片下。DRAM 用作主存和图形系统的帧缓冲区。
SRAM 将每个位置存储在双稳态存储单元中。每个单元由六个晶体管组成。
双稳态是指电路在两个不同的电压状态下无限期稳定。
对于 SRAM,只要有电,就永远地保持它的值。即使有干扰,当干扰消除,电路也会恢复到稳定值。
DRAM 将每个位置存储为充电一个电容器。 DRAM 该单元由电容器和访问晶体管组成。
DRAM 对干扰非常敏感。当电容的电压被扰乱后,就永远不会恢复了。
只要有电源,SRAM是持续的。和DRAM不同的,不需要刷新。SRAM的存取比DRAM快。SRAM对光和电噪声等干扰不敏感。其代价是SRAM电池比DRAM电池使用更多的晶体管,密度更低,价格更贵,功耗更大。
DRAM 芯片被分为 d 每个超单元包括每个超单元 w 个 DRAM 单元,w 一般为 8。当从 DRAM 读取数据时,可以一次读取一个超单元的数据(可以近似地将超单元理解为字节)。
DRAM 中超单位按行列组织,DRAM 还有一个行缓冲区。
发送行地址和列地址 DRAM,DRAM 将相应的超单元内容发回内存控制器,读取数据。
共享相同的行地址和列地址 DRAM 芯片地址引脚。
- 内存控制器发行地址 i,DRAM 将整个第 i 行复制到内部的行缓冲区。
- 内存控制器发来列地址 i,DRAM 从缓冲区复制超单元 (i,j) 并发送给内存控制器。
许多 DRAM 芯片封装在插入主板的扩展槽。
常用的是。
例如,内存模块包含内存模块 8 个 DRAM 芯片,每个 DRAM 包含 8M 个超单元,每个超单元存储一个字节(8bit)。,DRAM 0 存储第一个字节,DRAM 1 存储第 2 按此类推,个字节。
取出内存地址 A 内存控制器将首先处理一个字 A 转换为超单元地址 (i,j),然后是内存模块 i,j 广播到每个 DRAM。作为响应,每一个 DRAM 输出它的 (i,j) 超单元的 8 合并成一个位内容 64 将位字返回内存控制器。
主存由多个内存模块连接到内存控制器聚合成。
有些已经优化了 DRAM:
- :第二次连续访问位于同一行的超单元时,FPM DRAM 可直接从缓冲区获取数据。
- :FPM DRAM 增强的形式更快。
- :常规的、FPM 和 EDO 都是异步。就效果而言,SDRAM 它的超单元内容输出速度比异步存储器快。
双倍数据速率同步 DRAM(DDR SDRAM) :对 SDRAM 一种增强使速度翻倍。 DDR SDRAM 将预留缓冲区的大小划分为提高有效带宽的小区域:DDR(2位)、DDR2(4位)、DDR3(8位)。位置越多,速度越快,几乎翻倍。视频 RAM (VRAM) :它用于图形系统的帧缓冲区 FPM DRAM 类似。VRAM 允许并行读写内存。因此,系统可以用帧缓冲区的像素,系统可以用帧缓冲区的像素刷屏幕。
现在大部分的计算机都用了
DRAM 和 SRAM 断电后会丢失信息,所以是易失性存储器。
ROM 只读存储器,但实际上有一些 ROM 可读也可写。
可编程 ROM (PROM) :只能被编程一次。可擦写可编程 ROM (EPROM) :数千次可以擦除和重编程。电子可擦除 PROM (EEPROM) :类似于 EPROM,但是可以重编10万次。闪存 :基于 EEPROM 一种存储技术。闪存无处不在,固态硬盘是一种基于闪存的磁盘驱动器 。
存储在 ROM 设备中的程序通常被称为
数据流通过
总线是一组并行的导线,能携带地址、数据和控制信号。
- CPU 将地址 A 放到内存总线上。
- 主存从总线读出 A,取出字 x,然后将 x 放到总线上。
- CPU 从总线读出字 x,并将它复制到相应寄存器中。
- CPU 将地址 A 放到内存总线。主存读出这个地址,并等待数据字。
- CPU 将数据字 y 放到总线上。
- 主存从总线读数据字 y,并将它存储在地址 A。
6.1.2 磁盘存储
磁盘由
每个表面由一系列同心圆(称为
名词
磁盘容量:一个磁盘能够存储的最大位数,由以下因素决定:
记录密度 :单独决定一个扇区可以存储多少bit(或者至少是磁道的一部分)磁道密度 :相邻的磁道可以放置得多临近。面密度 :记录密度与磁道密度的乘积。决定了整个磁盘的存储容量。
磁盘容量公式:
磁盘容量=每个扇区的字节数 * 每个磁道上的平均扇区数 * 每个盘面的平均磁道数 * 一个盘片的盘面数 * 磁盘中盘片的数量
例如,假设我们有一个带有5个磁盘的磁盘,每个扇区512字节,每个表面20,000个磁道,每个磁道平均300个扇区。则磁盘的容量为:
注意,制造商表示磁盘容量的单位是GB (GB)或TB (TB),其中1GB = 10^9字节,1tb = 10^12字节。
DRAM 和 SRAM 相关的单位中 K = 2^10,磁盘、网络、速率、吞吐量相关的单位中 K=10^3。
注:磁盘格式化会填写间隙、标识出有故障的柱面、在每个区中预留出一组柱面作为备用。所以格式化容量要比最大容量小。
磁盘用
读写头位于
磁盘读写数据时
对扇区的访问时间包括三部分:
**寻道时间:**为了读取目标扇区的内容,传动臂首先要将读写头定位到包含目标扇区的磁道上。
现代驱动器的平均寻道时间为 3~9 ms,最大为 20 ms。(机械原理)
这个时间除
- 旋转时间依赖于磁盘的旋转速度和读写头到达目标磁道时的位置。
- 最大旋转时间是旋转速度的倒数,平均旋转时间是最大旋转时间的一半。
盘片以
设磁盘的旋转速度为RPM,则最大旋转时间(以秒为单位),为: T m r = ( 1 / R P M ) ∗ ( 60 s e c s / 1 m i n ) Tmr=(1/RPM)*(60secs/1min) Tmr=(1/RPM)∗(60secs/1min) 平均旋转延迟,Tavg旋转时间,只是Tmax旋转时间的一半。一般的旋转时间是指的平均旋转时间: T a r = ( 1 / R P M ) ∗ ( 60 s e c s / 1 m i n ) / 2 Tar=(1/RPM)*(60secs/1min)/2 Tar=(1/RPM)∗(60secs/1min)/2 可以简化为王道书上的,其中r为磁盘每秒的转数 T r = 1 / 2 r Tr=1/2r Tr=1/2r 对于硬盘,典型的旋转速度为5400 转/分,相当于一周11.1ms, 则Tr为5.55ms;
Tr=(1/5400)*60/2=11.1ms/2=5.55ms
对于软盘,其旋转速度为300600转/分,则T为50100ms。
**传送时间:**平均传送时间是读写头读写完整个扇区的时间。一个扇区的传输时间取决于转速和每个轨道扇区的数量。
王道书上:
传送时间取决于磁盘的旋转速度和每次读写的字节数b。N为一个磁道上的字节数
旋转时间一般和寻道时间差不多,而传送时间相对可以忽略不计,因此
例题:
例题:
现代磁盘呈现为一个逻辑块的序列,每个逻辑块是扇区大小的整数倍,最简单的情况下,逻辑块的大小为一个扇区,即 512 字节。块从0开始编号,块号是一系列增长的数字。
磁盘控制器保持物理扇区和逻辑块之间的映射。当操作系统读写磁盘时,发送一个
系统总线与内存总线都是与 CPU 相关的,而 IO 总线与 CPU 无关。
Intel 的**外部设备互连总线(PCI)**就是一种 IO 总线(广播总线)。
IO 总线速度相比于系统总线和内存总线慢,但是可以容纳种类繁多的第三方 IO 设备。
连接到 IO 总线的
通用串行总线(USB) :USB 总线是一个广泛使用的标准 ,连接各种 IO 设备,包括键盘、鼠标等。- **显卡/显示适配器:**负责代表 CPU 在显示器上画像素。
- **主机总线适配器:**连接磁盘。常总的磁盘接口是
SCSI 和 SATA 。其中 SCSI 比 SATA 更快也更贵。
CPU 使用
假设磁盘控制器映射到端口 0xa0,
- CPU 依次发送命令字、逻辑块号、目的内存地址到 0xa0,发起一个磁盘读。因为磁盘读的时间很长,所以此后 CPU 会转去执行其他工作。
2. 磁盘收到读命令后,将逻辑块号翻译成一个扇区地址,读取该扇区的内容,并将内容直接传送到主存,不需要经过 CPU (这称为
3. DMA 传送完成后,即磁盘扇区的内容安全地存储在主存中后,磁盘控制器给 CPU 发送一个中断信号来通知 CPU。
6.1.3 固态硬盘
一个固态硬盘中封装了一个
一个闪存由 B 个块的序列组成,每个块由 P 页组成,页的大小为 512byte~4kb。数据以页为单位进行读写。
对于 SSD 来说,
- 擦除块需要相对较长的时间。
- 如果写操作试图修改一个已经有数据的页,那么这个块中所有带有用数据的页都必须复制到一个新的块,然后才能向该页写数据。
**SSD 相比于旋转磁盘的优点:**由半导体存储器构成,没有移动部件,所以更结实,随机访问也更快,能耗更低。
基于闪存(flash memory)的存储技术
6.1.4 存储技术趋势
**性能上:**SRAM > DRAM > SSD > 旋转磁盘
DRAM 和 磁盘的性能滞后于 CPU 的性能提升速度,两者之间的差距越来越大。
6.2 局部性
实际上弥补CPU和内存之间差距的关键,是程序的局部性。
局部性是程序的一个基本属性。具有良好局部性的程序倾向于
现代计算机系统的各个层次,从硬件到操作系统到应用程序都利用了局部性。
6.2.1 对程序数据引用的局部性
for(int i=0; i 上例中,sum 具有好的时间局部性,向量 v 具有好的空间局部性。
这里对向量 v 中元素的访问是顺序访问的,称为
6.2.2 取指令的局部性
程序指令存放在内存中,CPU 需要读这些指令,因此取指令也有局部性。比如 for 循环中的指令具有好的时间局部性和空间局部性。
6.2.3 局部性小结
- 重复引用相同变量的程序有好的时间局部性。
- 对于步长为 k 的引用模式的程序,k 越小,空间局部性越好。
- 对于取指令来说,循环有好的时间和空间局部性。循环体越小,循环迭代次数越多,局部性越好。
6.3 存储器层次结构
6.3.1 在存储器层次结构中的缓存
一般而言,高速缓存(cache)是一个小而快速的存储设备。使用高速缓存的过程称为缓存(caching)。
**缓存的具体实现:**数据总是以块大小为传送单元(transfer unit)在第 k 层和第 k+1 层之间来回拷贝的。虽然在层次结构中任何一对相邻的层次之间块大小是固定的,但是其他的层次对之间可以用不同的块大小。
一般而言,层次结构较低的层(离 CPU 较远)的设备访问时间较长,因此为了补偿这些较长的访问时间,倾向于使用较大的块。
当需要 k+1 层的某个数据对象 d 时,如果 d 恰好缓存在 k 层中,就称为缓存命中。
缓存不命中时,第 k 层的缓存从 第 k+1 层缓存中取出包含 d 的块。
如果第 k 层缓存已经满了,需要根据替换策略选择一个块进行覆盖 (替换),未满的话需要根据放置策略来选择一个块放置。
冷不命中 :一个空的缓存称为冷缓存 ,冷缓存必然不命中,称为冷不命中。- **冲突不命中:**常用的放置策略是将 k+1 层的某个块限制放置在 k 层块的一个小的子集中。比如 k+1 层的块 1,5,9,13 映射到 k 层的块 0。这会带来冲突不命中。
容量不命中 :当访问的工作集的大小超过缓存的大小时,会发生容量不命中。即缓存太小了,不能缓存整个工作集。
寄存器文件的缓存由编译器管理,L1,L2,L3 的缓存由内置在缓存中的硬件逻辑管理,DRAM 主存作为缓存由操作系统和 CPU 上的地址翻译硬件共同管理。
6.3.2 存储器层次结构概念小结
存储器层次结构行之有效,因为较慢的设备比较快的设备更便宜,还因为程序偏向于展示局部性:
- 利用时间局部性,同一数据对象可能会被多次使用
- 利用空间局部性,块通常包含有多个数据对象
6.4 高速缓存存储器
L1 高速缓存的访问速度约为 4 个时钟周期,L2 约 10 个周期,L3 约 50 个周期。
当 CPU 执行一条读内存字 w 的指令,它首先向 L1 高速缓存请求这个字,如果 L1 没有就向 L2,依此而下。
6.4.1 通用的高速缓存存储结构
假设一个计算机系统中的存储器地址有 m 位,形成 M =2^m 个不同的地址。m 个地址为划分为
高速缓存被组织成 S=2^s 个
当 CPU 要从地址 A(由m个地址位组成) 处读一个字时:
- A 中的 s 个组索引位告诉我们在哪个组中
- A 中的 t 个标记位告诉我们在这个组中的哪一行:当且仅当这一行设置了有效位并且标记位与 A 中的标记位匹配时,才说明这一行包含这个字。
- A 中的 b 个块偏移位告诉我们在 B 个字节的数据块中的字偏移。
使用高位做标记位,可以避免连续的块被映射到同一高速缓存组中。
假设一个系统中只有 CPU、L1 高速缓存和主存。
当 CPU 执行一条从内存读字 w 的指令,如果 L1 有 w 的副本,就得到 L1 高速缓存命中;如果 L1 没有,就是缓存不命中。
当缓存不命中,L1 会向主存请求包含 w 的块(L1 中的块就是它的高速缓存行)的一个副本。当块从内存到达 L1,L1 将这个块存在它的一个高速缓存行里,然后从中抽取出字 w,并返回给 CPU。
高速缓存确定一个请求是否命中,然后抽取出被请求的字的过程分为三步:
组选择 行匹配 字抽取
直接映射高速缓存 :每个组只有一行,即 E=1。组相联高速缓存 :每个组有多行,1全相联高速缓存 :只有一个组,E=C/B。
6.4.2 直接映射高速缓存
每个组只有一行(E=1)的高速缓存被称为直接映射高速缓存
从 w 的 m 位地址中抽取出 s 个组索引位,并据此选择相应的高速缓存组。
因为直接映射高速缓存每个组只有一行,只要这一行设置了有效位且标记位相匹配,就说明想要的字的副本确实存储在这一行中。
从 w 的地址中抽取出 b 个块偏移位,块偏移位提供了所需的字的第一个字节的偏移。
缓存不命中时需要从下一层取出被请求的块,然后将其存储在组索引位指示的组中的高速缓存行中。
因为直接映射高速缓存每个组只有一行,所以替换策略很简单:用新取出的行替换当前行。
标记位和索引位连接起来标识了整个内存中的所有块,而高速缓存中的高速缓存组(块)是少于内存中的块数的。因此位于不同标记位,相同组索引位的块会映射到高速缓存中的同一个高速缓存组。
在一个高速缓存组中存储了哪个块,可以由标记位唯一地标识。
理解:对于主存中的整个地址空间,根据标记位不同将其分为了若干个部分,每个部分可以单独且完整地映射到高速缓存中,且刚好占满整个直接映射高速缓存。
冲突不命中在直接映射高速缓存中很常见。因为每个组只有一行,不同标记位的块会映射到同一行,发生冲突不命中。
6.4.3 组相联高速缓存
直接映射高速缓存中冲突不命中造成的问题是源于每一个组只有一行,组相联高速缓存(set associative cache)放松了这条限制,所以每个组都保存了有多于一行的高速缓存
与直接映射高速缓存一样,组索引位标识组。
组相联高速缓存中的行匹配更复杂,因为要
注意:组中的任意一行都可能包含映射到这个组的内存块,因此
与直接映射高速缓存一样,块偏移位标识所请求的字的第一个字节。
- **随机替换策略:**随机选择要替换的行
- **最不常使用策略:**替换在过去某个时间窗口内引用次数最少的一行。
- **最近最少使用策略:**替换最后一次访问时间最久远的那一行。
因为存储器层次结构中越靠下,不命中开销越大,好的替换策略越重要。
6.4.4 全相联高速缓存
全相联高速缓存由一个包含所有高速缓存行 (E=C/B) 的组组成。
因为高速缓存电路必须并行地搜索不同组已找到相匹配的标记,所以全相联高速缓存只适合做小的高速缓存。
DRAM 主存采用了全相联高速缓存,但是因为它采用了虚拟内存系统,所以在进行类似行匹配的页查找时不需要对一个个页进行遍历。
全相联高速缓存中只有一个组,所以地址中没有组索引位,只有标记位和块偏移位。
与组相联高速缓存一样。与组相联高速缓存的区别在于规模大小
6.4.5 有关写的问题
写相比读要复杂一些。
写命中(写一个已经缓存了的字 w)的情况下,高速缓存更新了本层的 w 的副本后,如何处理低一层的副本有两种方法:
直写 :立即将 w 的高速缓存块写回到低一层中。-
- 优点:简单
- 缺点:每次写都会占据总线流量
写回 :尽可能地推迟更新,只有当替换算法要驱逐这个更新过的块时,才把它写到低一层中。-
优点:利用了局部性,可以显著地减少总线流量。 - 缺点:增加了复杂性。必须为每个高速缓存行维护一个额外的修改位,表明此行是否被修改过。
写分配 :加载相应的低一层的块到本层中,然后更新这个高速缓存块。-
- 优点:利用写的空间局部性
- 缺点:每次不命中都会导致一个块从低一层传送到高速缓存
非写分配 :避开高速缓存,直接把这个字写到低一层中
直写一般与非写分配搭配,两者都更适用于存储器层次结构中的较高层。
因为硬件上复杂电路的实现越来越容易,所以现在使用写回和写分配越来越多。
6.4.6 指令高速缓存和统一高速缓存
- **i-cache:**只保存指令的高速缓存。i-cache 通常是只读的,因此比较简单。
- **d-cache:**只保存程序数据的高速缓存。
- **统一的高速缓存:**既保存指令又保存程序数据。
现代处理器一般包括独立的 i-cache 和 d-cache,其中两个原因如下:
- 使用两个独立的高速缓存,CPU 可以同时读一个指令字和一个数据字。
- 可以确保数据访问不会与指令访问形成冲突不命中(不过可能会使容量不命中增加)。
6.4.7 高速缓存参数的性能影响
-
高速缓存的性能指标 -
**命中率:**命中的内存引用比率。
-
命中时间 :从高速缓存传送一个字到 CPU 的时间,包括组选择、行确认和字抽取的实践。 -
**不命中处罚:**不命中产生的额外时间消耗。
几个影响因素 -
高速缓存大小:较大的高速缓存可以提高命中率,但是会运行得更慢,即增加命中时间。
-
块大小:较大的块更能利用空间局部性以提高命中率。但是对于给定的总容量,块越大高速缓存行就越少,不利用利用时间局部性。较大的块因为传送时间更长,所以也会增加不命中处罚。现代处理系统的高速缓存块一般为 64 字节。
-
相联度:参数E的选择的影响(每个组中高速缓存行数)。E越高优点是:降低了高速缓存由于冲突不命中出现抖动的可能性。缺点:实现起来昂贵;增加命中时间;增加不命中处罚。
-
写策略:高速缓存越往下层,越可能使用写会而不是直写策略。
-
6.5 编写高速缓存友好的代码
- 让最常见的情况运行得快
- 在每个循环内部使缓存不命中数量小
6.6 综合:高速缓存对程序性能的影响
存储器山(memory mountain)
6.7 小结
程序员可以通过编写有良好空间和时间局部性的程序来显著地改进程序的运行时间。利用基于 SRAM 的高速缓存存储器特别重要。
__EOF__
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-joOYTzlM-1652894096558)(https://blog.csdn.net/450go/p/16286735.html)]Huilin 本文链接:https://blog.csdn.net/450go/p/16286735.html关于博主:评论和私信会在第一时间回复。或者直接私信我。版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!声援博主:如果您觉得文章对您有帮助,可以点击文章右下角**【[推荐](javascript:void(0)😉】**一下。您的鼓励是博主的最大动力!