3.1 存储系统概述
存储器分级结构
目前的特点是:
- 速度快 价格贵 容量小
- 速度慢 价格低 容量大
在设计存储系统时,我们希望性能高、借个地,依据程序局部性原理,在存储器容量、速度、价格等方面的因素中综合考虑,建立了分层次的存储器体系结构。
程序局部性原理
在某一段时间内频繁访问某一局部的存储器地址空间,而对此范围之外的地址空间很少访问的现象。
时间局部性:最近被访问的信息很可能还要被访问。
空间局部性:最近被访问的信息临近地址的信息也可能被访问。
多级结构
<!–
多级结构图
–>
- 高速缓存(cache)。是计算机系统中的一个高速小容量半导体存储器;对性能的不同要求还可以分为一级cache和二级cache;
- 主存储器,简称主存。是计算机系统的主要存储器,主要用来存放计算机运行期间的大量程序和数据;
- 外存储器,简称外存,是大容量辅助存储器。
存储器之间的连接关系:
- 缓存-主存: 解决CPU与主存速度不匹配
- 速度接近缓存,高于主存,容量、价格接近主存。
- 主存-外存(辅存): 解决存储系统容量
- 容量接近外存,速度接近主存,价格接近外存。
存储器分类
- 按存储介质分类:
- 半导体器材
- 磁性材料
- 光盘存储器
- 按存取方式分类:
- 随机存取存储器
- 顺序存取存储器
- 半顺序(直接)存取存储器
- 按读写功能分类:
- 只读存储器(ROM)
- 随机存取存储器(RAM)
- 按信息易失性分类:
- 易失性存储器
- 非易失性存储器
- 与CPU耦合程度:
- 主存
- 高速缓存
- 外存
存储器编址和端模式
按字编址:
- 字存储单元,存放一个机器字,相应的单元地址为字地址。
按字节编址: - 字节存储单元,存放一个字节,相应的单元地址为字节地址。
端模式:
- 大端 低字节高地址
- 小端 低字节低地址
<!– CSAPP 图片 –>
存储器的技术指标
- 存储容量: 一个存储器中可存储的信息比特数(以为单位)
- 存储容量可以表示为:$ 存储字数(存储单元数)\times 存储字长(每单元的比特数)$
- 通常的KB MB即为 $1K \times 8bit$、$1M \times 8bit$
- 存取时间: 存储器访问时间. 从接收到命令到信息被读出或写入的时间. 取决于存储介质的物理特性和寻址部件的结构.
- 存储周期(存取周期): 完成一次完整存取操作所用的时间.
- 即CPU连续两次访问存储器的最小时间间隔.
- 通常存储周期略大于存取时间.
- 存储器带宽(数据传输速率): 单位时间里存储器所存取的信息量。
- 通常以 位/秒 或者 字节/秒 做度量单位
- 若系统总线宽度为 $W$ 位,则 $ 带宽=W \div 存取周期(bit/s) $
存取时间、存储周期、存储器带宽反映了存储器的速度指标。
3.2 静态随机存取存储器
静态存取存储器(SRAM)优点是存取速度快,但存储密度和容量不如DRAM大.
基本的静态存储元阵列
存储元: SRAM使用一个*锁存器(触发器)*做为存储元. 需要附加直流电使记忆电路保持 0 或者 1 的状态
三组信号线:
- 地址线:最大寻址范围为 $2^{地址线数}$ 。
- 数据线:表示存储器的字长,则存储器的位元总数为 $ 地址线 \times 数据线 $
- 控制线:R/W
基本的SRAM逻辑结构
SRAM芯片大多采用双译码方式,便于组织更大的存储容量.
通过二级移码.将地址分为x,y两部分.
$$ 芯片的存储容量=2^M \times N = 存储单元数 \times 存储单元的位数$$ $$ M:地址线根数 $$ $$ N:数据线根数 $$
同时芯片的读写是互锁的,读时不写,写时不读.
3.3 动态随机存取存储器
存储元: DRAM存储器的存储位元是由一个MOS晶体管和电容器组成的记忆电路。
数据被存放在电容C中,电容中有电荷为1,无电荷为0
逻辑结构
与SRAM的不同:
- 增加了行地址锁存器和列地址锁存器
- 增加了刷新计数器和相应的控制电路
由于DRAM存储容量较大,因此增加了地址锁存器、采取行列地址分时传送的方式,例如容量为 $ 1M $ 的DRAM只需要10条地址线即可,通过分时传送实现20条的效果。
如 $ 4M \times 8 $大小的存储器:
$$
数据线: 8 \
地址线:\frac{\log_2{4M}}{2}=11
$$
读写时序
暂略
刷新周期
DRAM存储位元是基于电容器上的电荷量存储,这个电荷量随着时间和温度而减少,因此必须定期地刷新,以保持它们原来记忆的正确信息。
有两种刷新方式:
- 集中式刷新:
DRAM中的所用行在每一个刷新周期中都被刷新,这样做的优点是存取速度比较快。
但是集中刷新存在死区,刷新时不能对数据进行读写, - 异步(分散式)刷新:
将每一行的刷新插入到正常的读写周期之中。
前半段用于读写,后半段用于刷新。这样设计避免了死区出现,但是增长了系统的存取周期,降低了征集速度。
存储器容量扩展
位扩展
给定的芯片字长位数较短,不满足设计需要,因此需要扩展位数来满足设计。
在位扩展中:
- 地址线公用
- 控制线公用
- 数据线单独连接。
扩充后的寻址范围不变,但每个存储单元数据位数发生了变化。
例如存储芯片为 $1M \times 4$ 容量, 需要设计一个 $ 1M \times 8 $ 的存储器,我们需要用到2片存储芯片, 读取的地址范围不变,但是读取到的数据为8位
计算芯片数公式为:
$$
d= \frac{设计要求的存储器容量}{已知芯片存储器容量}
$$
字扩展
给定的芯片存储容量较小, 不满足设计需要,因此需要多片串联来满足设计。
在字扩展中:
- 地址线公用
- 控制线 $ R/\overline W $公用,$ \overline E $ 不公用,使能端需要决定片选信号。
- 数据线公用
扩充后寻址范围增大,片选信号由地址编码中高位编译而来。
芯片数计算同上
字位双向扩展
同时进行字、位扩展,芯片数计算同上。
在扩展时先进行为扩展,在进行字扩展。
3.4 ROM EPROM EEPROM FLASH
- 只读存储器 ROM
- 可编程ROM(PROM)
- 光擦除ROM(EPROM)
- 电擦除ROM(EEPROM)
- FLASH存储器(闪速存储器)
- 高密度, 巨大的存储容量
- 非易失, 存放数据在没有电源的情况下长期保存.
<!– 表格比较 –>
3.5 并行存储器
为了解决CPU和主存速度不匹配的问题, 提出了以下几种解决方案:
- 芯片技术
- 提高芯片访问速度,采用高速主存储器
- 增加存储器字长等
- 结构技术
- 双端口存储器: 采用并行操作
- 交叉存储器:
- 系统结构技术
- 在CPU与主存之间插入Cache
双端口存储器
有两组相互独立的读写控制电路.
- 当两个端口不发生冲突时可以同时进行存取.
- 当两个端口读取统一单元时,通过设置BUSY标志,通过判断逻辑设置优先级,暂时关闭另一端口
特点:
- 采用空间并行技术
- 某一时刻可以同时对两个不同的存储单元进行读写, 相当于速度增加了一倍.
交叉存储器
存储器一般由若干存储模块组成,其中的数据有两种存储方式:顺序方式、交叉方式
两种方式的地址分为两部分:模块选择以及块内地址。
- 顺序方式
- 所有的数据存放在同一模块的相邻地址中
- 地址高位选择模块
- 地址低位选择块内地址
- 特点是一个模块工作其他的不工作
- 优点:一个模块故障其他的不影响,同时扩充容量比较方便
- 缺点:串行工作,带宽受到限制
- 交叉方式
- 所有数据储存在相邻的不同模块中,地址不连续。
- 地址高位选择块内地址
- 地址低位选择模块
- 特点是连续地址分布在相邻的不同模块内,同一个模块内的地址都是不连续的
- 优点:对连续字的块传送可以实现多模块流水线并行存取,提高了存储器带宽。适合成批数据处理
交叉方式存储的存储周期和流水线类似。
与前面介绍的流水线不同,这里每一级的时间为总线传送周期,是固定的值。
因此m个模块的存储周期(流水充满时间)为: $$ T=m\tau $$
连续读取m个的时间为: $$ t_1=T+(m-1)\tau $$
顺序方式读取时间为: $$ t_2=mT $$
由此,交叉存储器采用了空间并行技术.
3.6 Cache存储器
原因:
- CPU和主存速度存在诧异
- CPU和I/O争访存
基本原理
- 介于CPU和主存之间的小容量存储器,但存储速度比主存快.
- cache能高速的向主存提供指令和数据,加快程序执行速度.
- 由高速的SRAM组成.
- 所有功能由硬件实现,对程序员是透明的.
设计依据:
- Cache和程序局部性原理联系,最近访问的数据下次访问可能在这附近.
- CPU与Cache之间的数据传送是以字为单位,主存与Cache之间的数据传送是以块为单位。
- CPU请求数据的时候同时向Cache和主存的Cache控制逻辑发送地址,如果Cache中存在则立刻传给CPU
- 否则主存读周期时将此字从主存读出送到CPU, 同时将整个块送到cache
cache组成:
Cache存储体: 存放由主存调入的指令与数据块
地址转换部件: 建立目录实现从主存到Cache地址的转换
替换部件:缓存已满时按照一定策略对数据进行替换,并修改地址转换部件.
cache命中率:
理想状态下Cache的命中率应接近于1.
设 $N_C$ 表示Cache完成存取的总次数, $N_M$ 表示主存完成的总次数,则 $N_C+N_M$ 表示CPU请求的总次数,我们对命中率 $h$ 定义为:
$$ h=\frac{N_C}{N_C+N_M} $$
$t_c$ 表示命中时cache访问时间,$ t_m $表示未命中时主存访问时间,$1-h$ 表示未命中率(缺失率),则**cache/主存系统的平均访问时间 $t_a$ 为:
$$ t_a=ht_c+(1-h)t_m $$
我们追求的目标是 $t_a$ 接近于 $t_c$ 设 $ r=\frac{t_m}{t_c}$ 表示访问时间之比, $e$ 表示访问效率,则:$$ e=\frac{t_c}{t_a}=\frac{t_c}{ht_c+(1-h)t_m}=\frac{1}{h+(1-h)r}=\frac{1}{r+(1-r)h} $$
平均访问时间还可表示为:$$ t_a=\frac{t_c}{e} $$
cache的地址映射
在选择映射方式时我们需要考虑:
- 硬件是否容易实现
- 地址变换速度是否快
- 缓存空间利用率是否高
- 缓存装入时发生冲突的概率
通常有三种映射方法:
- 全相联映射
- 主存中任意一块可以映射到cahche中的任意一块
- 主存块装入时主存块号和cache块号会记录在相联存储器中,查询时若相联存储器中存在的则cahce命中。
- 命中时取出对应块号,并将Cache块号和块内字号拼接成cache地址。
- 缺点是电路设计难,适合小容量cache
<!– 图片 –>
- 直接相联映射
- 直接相联映射是通过某种特定关系构建出从$主存块j$到$cache块i$的映射
- $$ i=j mode 2^c $$
- 其中 $i$ 为cache块号,$j$ 为内存块号,$c$ 为cache块数,是一个哈希表。
- 优点:硬件简单、成本低,地址变换速度快
- 缺点:冲突概率高(访问块号相距m整数倍的两个块,因两块映射同一行,需要置换。降低cache效率)(两个哈希值相同的块会产生冲突)
- 适合大容量Cache(更多行数,减少冲突)
- 组相联映射(使用最广泛)
- 组间直接映射、组内全相联映射
- Cache 分V组,每组K行,则 $cache块数M=K \times V $
- $q$ 为cache组号,$j$ 为主存块号,$v$ 为cache组数
- $$ q=j \quad mod \quad v $$
对于组相联映射有如下几个参数需要注意:
- 主存块号
- 映射关系
- cache组号
- cache块号
对于块内地址,分为内存块号和块内地址,
内存块号分为*标记(s-d)和组号(d)*两部分
- 块内地址:由每块的大小决定位数
- 组号:由cache组数决定位数
- 通过内存块号计算出位数,减去组号就是标记
Cache的替换策略
- 最不常使用(LFU)算法
- 每行设置一个计数器,访问一次计数器+1
- 替换计数器数量小的
- 缺点:不能完全体现近期情况,如刚访问就开始替换
- 近期最少使用(LRU)算法
- 命中一次计数器清零,其他计数器+1
- 替换时替换数值最大的