深入理解计算机系统系列文章目录
第一章 计算机的基本组成
1. 内容概述
2. 计算机基本组成
第二章 计算机的指令和运算
3. 计算机指令
4. 程序的机器级表示
5. 计算机运算
6. 信息表示与处理
第三章 处理器设计
7. CPU
8. 处理器体系结构
9. 优化程序性能
10. 其他处理器
第四章 存储器和IO系统
11. 存储器的层次结构
12. 存储器和I/O系统
13. 存储器层次结构
前言
在简单的计算机系统模型中,存储器系统是一个线性的字节数组,而CPU能够在一个常数时间内访问每个存储器位置。
实际上,存储器系统(memorysystem)是一个具有不同容量、成本和访问时间的存储设备的层次结构。
CPU寄存器保存着最常用的数据。
靠近CPU的小的、快速的高速缓存存储器(cachememory)
作为一部分存储在相对慢速的主存储器(mainmemory)中数据和指令的缓冲区域。
主存缓存存储在容量较大的、慢速磁盘上的数据,
而这些磁盘常常又作为存储在通过网络连接的其他机器的磁盘或磁带上的数据的缓冲区域。
整体效果是一个大的存储器池,其成本与层次结构底层最便宜的存储设备相当,
但是却以接近于层次结构顶部存储设备的高速率向程序提供数据。
如果你理解了系统是如何将数据在存储器层次结构中上上下下移动的,
那么你就可以编写自己的应用程序,使得它们的数据项存储在层次结构中较高的地方,在那里CPU能更快地访问到它们。
这个思想围绕着计算机程序的一个称为局部性(locality)的基本属性。
具有良好局部性的程序倾向于一次又一次地访问相同的数据项集合,或是倾向千访问邻近的数据项集合。
具有良好局部性的程序比局部性差的程序更多地倾向于从存储器层次结构中较高层次处访问数据项,因此运行得更快。
我们将注意力集中在高速缓存存储器上,它是作为CPU和主存之间的缓存区域,因为它们对应用程序性能的影响最大。
参考资料
《深入理解计算机系统》
《深入浅出计算机组成原理》
一、存储技术
1. 随机访问存储器
随机访问存储器(Random-AccessMemory,RAM)分为两类:静态的和动态的。
静态RAM(SRAM)比动态RAM(DRAM)更快,但也贵得多。SRAM用来作为高速缓存存储器,既可以在CPU芯片上,也可以在片下。
DRAM用来作为主存以及图形系统的帧缓冲区。
1.1 静态RAM
SRAM将每个位存储在一个双稳态的(bistable)存储器单元里。
每个单元是用一个六晶体管电路来实现的。
这个电路有这样一个属性,它可以无限期地保持在两个不同的电压配置(configuration)或状态(state)之一。
其他任何状态都是不稳定的从不稳定状态开始,电路会迅速地转移到两个稳定状态中的一个。
原则上,钟摆也能在垂直的位置尤限期地保持平衡,
但是这个状态是亚稳态的(metastable)最细微的扰动也能使它倒下,而且一旦倒下就永远不会再恢复到垂直的位置。
由千SRAM存储器单元的双稳态特性,只要有电,它就会永远地保持它的值。
即使有干扰(例如电子噪音)来扰乱电压,当干扰消除时,电路就会恢复到稳定值。
1.2 动态RAM
DRAM将每个位存储为对一个电容的充电。
DRAM存储器可以制造得非常密集每个单元由一个电容和一个访问品体管组成。
但是,与SRAM不同,DRAM存储器单元对干扰非常敏感。
当电容的电压被扰乱之后,它就永远不会恢复了。
暴露在光线下会导致电容电压改变。
很多原因会导致漏电,使得DRAM单元在10~100毫秒时间内失去电荷。
幸运的是,计算机运行的时钟周期是以纳秒来衡量的,所以相对而言这个保持时间是比较长的。
内存系统必须周期性地通过读出,然后重写来刷新内存每一位。
有些系统也使用纠错码,其中计算机的字会被多编码几个位(例如64位的字可能用72位来编码),
这样一来,电路可以发现并纠正一个字中任何单个的错误位。
只要有供电,SRAM就会保持不变。
与DRAM不同,它不需要刷新。SRAM的存取比DRAM快。
SRAM对诸如光和电噪声这样的干扰不敏感。代价是SRAM单元比DRAM单元使用更多的晶体管,因而密集度低,而且更贵,功耗更大。
1.3 传统的DRAM
DRAM芯片中的单元(位)被分成d个超单元(supercell),
每个超单元都由w个DRAM单元(一个DRAM单元存放一个位信息)组成。
一个 d X w 的DRAM总共存储了dw位信息。
超单元被组织成一个r行c列的长方形阵列,这里rc=d。
每个超单元有形如(i,))的地址,这里1表示行,而)表示列。
信息通过称为引脚(pin)的外部连接器流入和流出芯片。
每个引脚携带一个1位的信号。
每个DRAM芯片被连接到某个称为内存控制器(memorycontroller)的电路,
这个电路可以一次传送w位到每个DRAM芯片或一次从每个DRAM芯片传出w位。
为了读出超单元 (i ’ j) 的内容,内存控制器将行地址1发送到DRAM,然后是列地址J。
DRAM把超单元(i’j)的内容发回给控制器作为响应。
行地址t称为RAS(RowAccessStrobe,行访问选通脉冲)请求。
列地址)称为CAS(ColumnAccessStrobe,列访问选通脉冲)请求。
注意,RAS和CAS请求共享相同的DRAM地址引脚。
电路设计者将DRAM组织成二维阵列而不是线性数组的一个原因是降低芯片上地址引脚的数量。
例如,如果示例的128位DRAM被组织成一个16个超单元的线性数组,地址为0~15,那么芯片会需要4个地址引脚而不是2个。
二维阵列组织的缺点是必须分两步发送地址,这增加了访问时间。
1.4 内存模块
DRAM芯片封装在内存模块(memorymodule)中,它插到主板的扩展槽上。
图6-5展示了一个内存模块的基本思想。示例模块用8个64Mbit的8MX8的DRAM芯片,总共存储64MB(兆字节),这8个芯片编号为0~7。
每个超单元存储主存的一个字节,而用相应超单元地址为(i’j)的8个超单元来表示主存中字节地址A处的64位字。
在图6-5的示例中,DRAMO存储第一个(低位)字节,DRAMl存储下一个字节,依此类推。
要取出内存地址A处的一个字,内存控制器将A转换成一个超单元地址(i’j),
并将它发送到内存模块,然后内存模块再将l和)广播到每个DRAM。作为响应,每个DRAM输出它的(i’j)超单元的8位内容。
模块中的电路收集这些输出,并把它们合并成一个64位字,再返回给内存控制器
1.5 增强的DRAM
快页模式DRAM (Fast Page Mode DRAM, FPMDRAM)。
扩展数据轮出DRAM (Extended Data Out DRAM, EDODRAM)。
同步DRAM (Synchronous DRAM, SDRAM)。
双倍数据速率同步DRAM。
视频RAM(VideoRAM,VRAM)。
1.6 非易失性存储器
虽然ROM中有的类型既可以读也可以写,但是它们整体上都被称为只读存储器(Read-OnlyMemory,ROM)。
ROM是以它们能够被重编程(写)的次数和对它们进行重编程所用的机制来区分的。
PROM+EPROM+EEPROM+flashmemory
1.7 访问主存
数据流通过称为总线(bus)的共享电子电路在处理器和DRAM主存之间来来回回。
总线是一组并行的导线,能携带地址、数据和控制信号。
取决千总线的设计,数据和地址信号可以共享同一组导线,也可以使用不同的。
同时,两个以上的设备也能共享同一总线。
控制线携带的信号会同步事务,并标识出当前正在被执行的事务的类型。
2. 磁盘存储
见上一节
3. 固态硬盘
4. 存储技术趋势
不同的存储技术有不同的价格和性能折中。
SRAM比DRAM快一点,而DRAM比磁盘要快很多。
另一方面,快速存储总是比慢速存储要贵的。
SRAM每字节的造价比DRAM高,DRAM的造价又比磁盘高得多。
SSD位于DRAM和旋转磁盘之间。
不同存储技术的价格和性能属性以截然不同的速半变化着。
虽然SRAM的性能滞后千CPU的性能,但还是在保持增长。
二、局部性
一个编写良好的计算机程序常常具有良好的局部性(locality)。
也就是,它们倾向于引用邻近于其他最近引用过的数据项的数据项,或者最近引用过的数据项本身。
这种倾向性,被称为局部性原理(principle of locality),是一个持久的概念,对硬件和软件系统的设计和性能都有着极大的影响。
局部性通常有两种不同的形式:时间局部性(temporal locality)和空间局部性(spatial locality)。
在一个具有良好时间局部性的程序中,被引用过一次的内存位置很可能在不远的将来再被多次引用。
在一个具有良好空间局部性的程序中,如果一个内存位置被引用了一次,那么程序很可能在不远的将来引用附近的一个内存位置。
现代计算机系统的各个层次,从硬件到操作系统、再到应用程序,它们的设计都利用了局部性。
在硬件层,局部性原理允许计算机设计者通过引入称为高速缓存存储器的小而快速的存储器来保存最近被引用的指令和数据项,从而提高对主存的访问速度。
在操作系统级,局部性原理允许系统使用主存作为虚拟地址空间最近被引用块的高速缓存。
类似地,操作系统用主存来缓存磁盘文件系统中最近被使用的磁盘块。
量化评价程序中局部性的一些简单原则:
- 重复引用相同变量的程序有良好的时间局部性。
- 对千具有步长为K的引用模式的程序,步长越小,空间局部性越好。
具有步长为1的引用模式的程序有很好的空间局部性。
在内存中以大步长跳来跳去的程序空间局部性会很差。 - 对千取指令来说,循环有好的时间和空间局部性。循环体越小,循环迭代次数越多,局部性越好。
三、存储器层次结构
概括来说,基于缓存的存储器层次结构行之有效,
是因为较慢的存储设备比较快的存储设备更便宜,还因为程序倾向于展示局部性:
- 利用时间局部性:
由于时间局部性,同一数据对象可能会被多次使用。
一旦一个数据对象在第一次不命中时被复制到缓存中,我们就会期望后面对该目标有一系列的访问命中。
因为缓存比低一层的存储设备更快,对后面的命中的服务会比最开始的不命中快很多。 - 利用空间局部性:
块通常包含有多个数据对象。
由千空间局部性,我们会期望后面对该块中其他对象的访问能够补偿不命中后复制该块的花费。
四、高速缓存存储器
早期计算机系统的存储器层次结构只有三层:CPU寄存器、DRAM主存储器和磁盘存储。
不过,由千CPU和主存之间逐渐增大的差距,
系统设计者被迫在CPU寄存器文件和主存之间插入了一个小的SRAM高速缓存存储器,
称为L1高速缓存(一级缓存),如图6-24所示。
L1高速缓存的访问速度几乎和寄存器一样快,典型地是大约4个时钟周期。
随着CPU和主存之间的性能差距不断增大,系统设计者在Ll高速缓存和主存之间又插入了一个更大的高速缓存,
称为L2高速缓存,可以在大约10个时钟周期内访问到它。
有些现代系统还包括有一个更大的高速缓存,称为L3高速缓存,
在存储器层次结构中,它位于L2高速缓存和主存之间,可以在大约50个周期内访问到它。
虽然安排上有相当多的变化,但是通用原则是一样的。
1. 读
2. 写
写的情况就要复杂一些了。
假设我们要写一个已经缓存了的字w(写命中,writehit)。
在高速缓存更新了它的w的副本之后,怎么更新w在层次结构中紧接着低一层中的副本呢?
最简单的方法,称为直写(write-through),就是立即将w的高速缓存块写回到紧接着的低一层中。
虽然简单,但是直写的缺点是每次写都会引起总线流量。
另一种方法,称为写回(write-back),尽可能地推迟更新,
只有当替换算法要驱逐这个更新过的块时,才把它写到紧接着的低一层中。
由于局部性,写回能显著地减少总线流扯,但是它的缺点是增加了复杂性。
高速缓存必须为每个高速缓存行维护一个额外的修改位(dirtybit),表明这个高速缓存块是否被修改过。
另一个问题是如何处理写不命中。
一种方法,称为写分配(write-allocate),加载相应的低一层中的块到高速缓存中,然后更新这个高速缓存块。
写分配试图利用写的空间局部性,但是缺点是每次不命中都会导致一个块从低一层传送到高速缓存。
另一种方法,称为非写分配(not-write-allocate),避开高速缓存,直接把这个字写到低一层中。
直写高速缓存通常是非写分配的。
写回高速缓存通常是写分配的。
建议在心里采用一个使用写回和写分配的高速缓存的模型。
这样建议有几个原因。
通常,由于较长的传送时间,存储器层次结构中较低层的缓存更可能使用写回,而不是直写。
例如,虚拟内存系统(用主存作为存储在磁盘上的块的缓存)只使用写回。
但是由于逻辑电路密度的提高,写回的高复杂性也越来越不成为阻碍了,我们在现代系统的所有层次上都能看到写回缓存。
所以这种假设符合当前的趋势。
假设使用写回写分配方法的另一个原因是,
它与处理读的方式相对称,因为写回写分配试图利用局部性。
因此,我们可以在高层次上开发我们的程序,展示良好的空间和时间局部性,而不是试图为某一个存储器系统进行优化。
3. 层次结构
到目前为止,我们一直假设高速缓存只保存程序数据。
不过,实际上,高速缓存既保存数据,也保存指令。
只保存指令的高速缓存称为i-cache。只保存程序数据的高速缓存称为d-cache。
既保存指令又包括数据的高速缓存称为统一的高速缓存(unifiedcache)。
现代处理器包括独立的i-cache和cl-cache。
这样做有很多原因。有两个独立的高速缓存,处理器能够同时读一个指令字和一个数据字。
i-cache通常是只读的,因此比较简单。
通常会针对不同的访问模式来优化这两个高速缓存,它们可以有不同的块大小,相联度和容量。
使用不同的高速缓存也确保了数据访问不会与指令访问形成冲突不命中,反过来也是一样,代价就是可能会引起容量不命中增加。
4. 高速缓存参数的性能影响
有许多指标来衡量高速缓存的性能:
- 不命中率(missrate)。
在一个程序执行或程序的一部分执行期间,内存引用不命中的比率。
它是这样计算的:不命中数量/引用数量。 - 命中率(hitrate)。
命中的内存引用比率。它等于1一不命中率。 - 命中时间(hittime)。
从高速缓存传送一个字到CPU所需的时间,包括组选择、行确认和字选择的时间。
对于L1高速缓存来说,命中时间的数量级是几个时钟周期。 - 不命中处罚(misspenalty)。
由千不命中所需要的额外的时间。
L1不命中需要从L2得到服务的处罚,通常是数10个周期;
从L3得到服务的处罚,50个周期;
从主存得到的服务的处罚,200个周期。
优化高速缓存的成本和性能的折中是一项很精细的工作,它需要在现实的基准程序代码上进行大量的模拟,因此超出了我们讨论的范围。
不过,还是可以认识一些定性的折中考量的。
- 高速缓存大小的影响
一方面,较大的高速缓存可能会提高命中率。
另一方面,使大存储器运行得更快总是要难一些的。
结果,较大的高速缓存可能会增加命中时间。
这解释了为什么L1高速缓存比L2高速缓存小,以及为什么L2高速缓存比L3高速缓存小。 - 块大小的影响
大的块有利有弊。
一方面,较大的块能利用程序中可能存在的空间局部性,帮助提高命中率。
不过,对千给定的高速缓存大小,块越大就意味着高速缓存行数越少,这会损害时间局部性比空间局部性更好的程序中的命中率。
较大的块对不命中处罚也有负面影响,因为块越大,传送时间就越长。
现代系统(如Corei7)会折中使高速缓存块包含64个字节。 - 相联度的影响
这里的间题是参数E选择的影响,E是每个组中高速缓存行数。
较高的相联度(也就是E的值较大)的优点是降低了高速缓存由于冲突不命中出现抖动的可能性。
不过,较高 的相联度会造成较高的成本。
较高的相联度实现起来很昂贵,而且很难使之速度变快。
每一行需要更多的标记位,每一行需要额外的LRU状态位和额外的控制逻辑。
较高的相联度会增加命中时间,因为复杂性增加了,另外,还会增加不命中处罚,因为选择牺牲行的复杂性也增加了。
相联度的选择最终变成了命中时间和不命中处罚之间的折中。
传统上,努力争取时钟频率的高性能系统会为L1高速缓存选择较低的相联度(这里的不命中处罚只是几个周期),
而在不命中处罚比较高的较低层上使用比较小的相联度。
例如,IntelCorei7系统中,L1和L2高速缓存是8路组相联的,而L3高速缓存是16路组相联的。 - 写策略的影响
直写高速缓存比较容易实现,而且能使用独立于高速缓存的写缓冲区(writebuffer),用来更新内存。
此外,读不命中开销没这么大,因为它们不会触发内存写。
另一方面,写回高速缓存引起的传送比较少,它允许更多的到内存的带宽用于执行DMA的1/0设备。
此外,越往层次结构下面走,传送时间增加,减少传送的数量就变得更加重要。
一般而言,高速缓存越往下层,越可能使用写回而不是直写。
五、编写高速缓存友好的代码
局部性比较好的程序更容易有较低的不命中率,
而不命中率较低的程序往往比不命中率较高的程序运行得更快。
- 让最常见的情况运行得快。
- 尽量减小每个循环内部的缓存不命中数量。
- 对局部变量的反复引用是好的,因为编译器能够将它们缓存在寄存器文件中(时间局部性)。
- 步长为1的引用模式是好的,因为存储器层次结构中所有层次上的缓存都是将数据存储为连续的块(空间局部性)
总结
基本存储技术包括随机存储器(RAM)、非易失性存储器(ROM)和磁盘。
RAM有两种基本类型。
静态RAM(SRAM)快一些,但是也贵一些,它既可以用做CPU芯片上的高速缓存,也可以用做芯片下的高速缓存。
动态RAM(DRAM)慢一点,也便宜一些,用做主存和图形帧缓冲区。
即使是在关电的时候,ROM也能保持它们的信息,可以用来存储固件。
旋转磁盘是机械的非易失性存储设备,以每个位很低的成本保存大量的数据,但是其访问时间比DRAM长得多。
固态硬盘(SSD)基于非易失性的闪存,对某些应用来说,越来越成为旋转磁盘的具有吸引力的替代产品。
一般而言,较快的存储技术每个位会更贵,而且容贵更小。
这些技术的价格和性能属性正在以显著不同的速度变化着。
特别地,DRAM和磁盘访问时间远远大于CPU周期时间。
系统通过将存储器组织成存储设备的层次结构来弥补这些差异,在这个层次结构中,较小、较快的设备在顶部,较大、较慢的设备在底部。
因为编写良好的程序有好的局部性,大多数数据都可以从较高层得到服务,
结果就是存储系统能以较高层的速度运行,但却有较低层的成本和容址。文章来源:https://www.toymoban.com/news/detail-600659.html
程序员可以通过编写有良好空间和时间局部性的程序来显著地改进程序的运行时间。
利用基于SRAM的高速缓存存储器特别重要。
主要从高速缓存取数据的程序能比主要从内存取数据的程序运行得快得多。文章来源地址https://www.toymoban.com/news/detail-600659.html
到了这里,关于深入理解计算机系统(13)_存储器层次结构的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!