在本章中我们会看看基本的存储技术——SRAM存储器、DRAM存储器、ROM存储器以及旋转的和固态的硬盘——并描述它们是如何被组织成层次结构的
如果程序需要的数据是存储在CPU寄存器中的,那么在指令的执行期间,在0个时钟周期就可以访问到它们,如果存储在高速缓存中,需要4-75个周期,如果存储在主存中,需要上百个周期,而如果存储在磁盘上,需要大约几千万个周期。
随机访问存储器RAM分为两类:静态的和动态的。静态的SRAM比动态的DRAM更快,但也更贵。SRAM用来作为高速缓存存储器可以在CPU芯片上也可以在片下。一个桌面系统的SRAM不会超过几兆字节,但是DRAM却有几百或几千兆字节。
SRAM:SRAM将每一个位存储在一个双稳态的存储单元里,每个单元是用一个六晶体管电路来实现的。这个电路有一个属性,它可以无限期保持在两个不同电压配置或状态之一。从不稳定的状态开始,电路会迅速转移到两个稳定状态中的一个——双稳态特性,由于SRAM存储器单元具有双稳态特性,只要有电,他就会永远保持它的值(0或1),即使有干扰,当干扰消除时,电路也会恢复到它的稳定值——抗干扰。
DRAM:DRAM使用非常小的电容来存储每个位,电容的典型值是几十毫微微法拉;由于电容容易漏电所以DRAM需要周期性地刷新来维持存储的数据(计算机运行的时钟周期是以纳秒来衡量的,DRAM漏电是在几十毫秒内);DRAM 单元由一个晶体管和一个电容组成,因此它能够以更高的密度存储更多的数据,但这也意味着它的速度较慢。
为了读出超单元(i,j)的内容,内存控制器将行地址i(RAS)和列地址j(CAS)发送到DRAM,DRAM把相应的内容发回给控制器作为相应。过程:发送行地址i,然后DRAM将整个行复制到一个内部行缓冲区,再发送列地址j,最后DRAM从内部行缓冲区中复制相应的内容发送到内存控制器(为什么这样设计:DRAM芯片是一个二维的,而不是一个线性的数组,通过这样来获取数据,可以减少芯片上地址引脚的数量,但会增加数据的访问时间)。每个超单元可以存储8bit的数据。
图中展示了一个内存模块,示例用8个DRAM芯片。每个DRAM芯片大小是8M×8,也就是8MB,所以这个内存模块是64MB的。每个超单元可以存储8bit的数据,那么对于8字节的数据就要使用8个超单元来存储。不过这8个超单元并不在同一个DRAM芯片上,而是平均分布在8个DRAM芯片上,其中DRAM0存储低8位,DRAM1存储下一个8位,以此类推。内存控制器需要这些数据时,会发送行地址和列地址,然后内存模块会将行地址和列地址广播到每个DRAM,每个DRAM都会输出它们对应的超单元数据,最终内存模块会将所有超单元的数据合并成一个64bit的数据返回给内存控制器。
前面的随机访问存储器是在有点的情况下才能存储信息,而磁盘存储在断电的情况下也能保存信息。
磁盘是由多个盘片构成的,每个盘片都有两面被称为表面,表面覆盖了磁性记录材料。盘片中央有一个可以旋转的主轴,它使得盘片以固定的旋转速率旋转,通常是5400-15000转每分钟(RPM)。磁盘表面存在着一组被称为磁道的同心圆,磁道以主轴为中心向外扩散,每个磁道被分为一组扇区,每个扇区包含相等的数据位,通常是512字节,这些数据被编码在扇区的磁性材料中。扇区之间用一些间隙分隔开,这些间隙中不存储数据位,而是用来存储扇区的格式化位。
对扇区的访问时间有三个主要的部分:寻道时间、旋转时间、传送时间。
寻道时间:平均寻道时间是3~9ms,最高可达20ms。
旋转时间:一旦读写头到了期望的磁道,驱动器就等到目标扇区的第一个位旋转到读写头下,而盘面位置是不可预期的,所以最大的旋转时间如下(以秒为单位,其中RPM是转每分钟):
传送时间:当目标扇区的第一个位位于读写头下面时,驱动器就开始读/写该扇区的内容了,一个扇区的传送时间依赖于旋转速度和每条磁道的扇区数目,因此粗略估计一个扇区的平均传送时间如下(以秒为单位):
综上:
示例:
固态硬盘SSD是一种基于闪存的存储技术是由半导体存储器构成的,一个SSD封装由一个或多闪存芯片和闪存翻译层组成,闪存芯片代替传统旋转磁盘中的机械驱动器,而闪存翻译层是一个硬件,它和磁盘控制器一样,将逻辑块的请求翻译成对底层物理设备的访问。SSD读比写快,这是由于底层闪存基本属性决定的。一个闪存由B个块的序列组成,每个块是由P页组成,通常页的大小是512字节~4KB,块是由32~128页组成的,块的大小为16KB~512KB。
数据是以页为单位读写的,只有在一页所属的整个块被擦除时候,才能够写这一页,在写入的时候由于闪存编程原理的限制,只能将1变成0,而不能将0变成1,所有擦除操作就是将所有的位变成1。因为这样,所以一个块被擦除之后,块中的每一个页都可以不需要再进行擦除就可以写一次。在大约进行100000次重复的写之后,块就会磨损,就不能再使用了。当然,它的编程原理也会将这些损耗平均下去。
例子:如下图变量sum具有较好的时间局部性,数组v具有较好的空间局部性:
高速缓存是一个小而快速的存储设备,他作为存储再更大更慢的设备中的数据对象的缓冲区域,使用高速缓存的过程称为缓存。存储器层次结构的中心思想是:对于每个k,位于k层的更快更小的存储设备作为位于k+1层的更大更慢的存储设备的缓存。
存储下一层数据对象总是以块大小作为传送单元在第k层和第k+1层之间来回复制的,位于k层的存储器被分为较少的块集合,每个块大小与k+1层的块的带下一样,在任何时候,位于k层的存储器包含第k+1层块的一个子集副本。
缓存命中:当程序需要第k+1层的数据时候,他首先在当前存储在第k层的数据块中检索是否包含目标数据的副本,如果有,就称为缓存命中。当发生缓存不命中时,第k层的缓存从第k+1层缓存中取出包含目标数据的那个块,如果第k层的缓存已经满了,可能就会覆盖现存的数据块,覆盖的过程被称为替换,被替换的块被称为牺牲块。决定替换哪一个块是由缓存的替换策略来控制的,会随机或者选择最后访问较远的块(LRU)。
缓存不命中种类:
有一个计算机系统,其中每一个存储器地址有m位,那么会形成M=2^m个不同的地址。一个机器的高速缓存被组织为一个有S个高速缓存组的数组,每个组缓存组包含E个高速缓存行,每个行是一个B字节的数据块、一个有效位指明这个行是否包含有意义的信息(为1有效为0无效),还有t个标记位(是当前块的内存地址的位的一个子集,唯一标识存储在这个高速缓存行中的块)组成的。高速缓存的结构可以用元组(S,E,B,m)来描述,高速缓存的大小指的是所有块的大小和,标记为不包括在内,所以大小=S×B×E。
如何寻找目标数据的副本:s个组索引位是一个到第S个组的索引之后通过标记位知道了数据在哪一个块并且过程中会检查有效位,找到后通过块偏移在数据块中查找目标数据。
根据每个组的高速缓存行数E,高速缓存被分为不同的类,其中每个组只有一行(E=1)的高速缓存被称为直接映射高速缓存。高速缓存确定一个请求是否命中,然后抽取出被请求的字的过程分为三步:组选择、行匹配、字抽取。
就是每个组多于一个行。
只有一个组的组相联高速缓存称为全相联高速缓存,没有组选择这一步。
书本上cache的映射例题一定要做一下