计组-07-存储器

计算机组成原理-07-存储器

前言

mark

1. 主存储器

1.1 基本概念

  • 回忆主存储器
    • 逻辑结果如下所示
    • 物理结果如下所示

mark

读写操作流程:

  • 指令执行的过程中需要访问主存的时候,
    • CPU首先把被访问单元的地址放入到MAR 中,然后通过地址线(注意是单向的)将主存地址送到主存的地址寄存器中
    • 以便地址译码器进行译码相应的单元,
    • 同时CPU将读写信号通过控制先送到主存的读写控制电路
  • 如果是写操作,那么CPU同时将要写的信息送到MDR中,在读写电路的控制下,经数据线(注意是双向的)将信号写入选中的单元
  • 如果是读操作,那么主存读出选中选中单元的内容送到数据线,然后送到MDR中
  • 需要注意的是:数据线的宽度和MDR的宽度是相同的,地址线的宽度和MAR的宽度是相同的
    • 若采用64位的数据线,那么在按照字节编址的方式下,每次最多可以存取8个单元的内容(存储体的列数)
    • 地址线决定了主存地址空间的最大寻址范围,如36位的地址最大寻址范围是0-(2^36)-1存储体的行数
    • 数据线和地址线数量共同反映了存储体的大小,若采用以上的存储方式,那么芯片的容量是(2^36)*64位(行*列)

存储体容量计算:

mark

具体存储如下所示:

  • 存储元:存储0或1的记忆单元(电容和开关组成)
  • 存储单元:由一行存储元组成
  • 存储字:一行存储元的位数
  • 存储矩阵:也叫存储体,是存储器的核心

mark

mark

  • 存储器和存储字长的关系

mark

上图存储体的缺点

  • 一次只能进行一次读写(只有一行的控制线起作用)
  • 优化是加入译码器 (n位地址 -> 2^n 的存储单元)
    • 本质是通过映射去实现
    • (n位地址 -> 2^n 的存储单元)
    • (n位地址 -> 2^n 的行数)

1.2 主存的简单模型

  • 存储器芯片电路如下所示

mark

  • 逻辑结构如下所示
    • 片选线:控制开关
    • 读写控制线:控制读写操作

mark

1.3 寻址

mark

对于上图结构而言:寻址

  • 如果存储的总容量为1KB,按字节寻址

    • 那么就有1K个存储单元
    • 每个存储单元的大小为1B = 8bit
  • 如果存储的总容量为1KB,按字寻址

    • 那么就有256个存储单元
    • 每个存储单元的大小为4B
  • 如果存储的总容量为1KB,按半字寻址

    • 那么就有512个存储单元
    • 每个存储单元的大小为2B
  • 如果存储的总容量为1KB,按双字寻址

    • 那么就有1024个存储单元
    • 每个存储单元的大小为8B=64bit

编址的概念如下所示:

  • 如果存储的总容量为1KB,按字节寻址
    • 那么就有1K个存储单元
    • 每个存储单元的大小为1B = 8bit
    • 需要地址线为10根数,地址为(0-1023)

mark

若按字进行编址

  • 也就是4个字节为一组
  • 通过高位来分辨组与组之间的不同
  • 具体编址如下所示:

mark

mark

但是按字编址带来的问题:如何存储数据

  • 大端存储:按照人的阅读模式存放(先放高位地址)
  • 小端存储:与上面相反(先放低位字节)

1.4 小结

mark

2. 半导体存储器

2.1 半导体存储器的基本结构

mark

2.2 RAM

2.2.1 RAM

  1. 半导体随机存储器(RAM)
    • 访问的内存位置与存放的地址无关
    • 只和电流的速度有关
  2. RAM分为以下两种类别
    • SRAM : 静态存储器
    • DRAM : 动态存储器

mark

  • 对比如下

mark

2.2.2 DRAM的刷新问题

  • DRAM的刷新是以行为单位的(减少了选通线的数量)
  • 刷新的周期为2ms

mark

  • 如何进行刷新的问题?

mark

2.2.3 SRAM读写周期

  1. 读周期

mark

mark

  1. 写周期

mark

mark

2.2.4 小结

mark

2.3 ROM

  • ROM只读存储器

mark

2.4 小结

mark

3. 存储器的概念

3.1 分类

  • 层次的角度来分
    • 高速缓冲存储器(cache)
    • 主存储器(主存,内存)
    • 辅助存储器(辅存,外存)

mark

  • 存储介质来分类
    • 磁盘 磁带
    • 磁芯存储器
    • 半导体存储器
  • 存储方式来分类
    • 随机存储器(RAM) : 存储时间与存储的物理位置无关
    • 只读存储器(ROM): 只能随机读出而不能写入
    • 串行访问存储器
      • 顺序存取存储器(磁带)
      • 直接存取存储器(磁盘)

3.2 性能指标

mark

3.3 层次化结构

mark

4. 主存和CPU的连接

4.1 主存容量的扩展

4.1.1 位扩展

  • 当CPU的数据线与存储芯片的数据位数不相等时,需要对存储芯片进行位扩展,假设使用8K*1位的RAM芯片和8K*8位的CPU,使得数据位数和CPU的数据线位数相等。
  • 如下图所示:

mark

  • 扩展后如下所示:
    • 地址并行的送至地址线
    • 数据进行位扩展送到CPU
    • 相当于合并为一个8K*8位的存储器

mark

4.1.2 字扩展

  • 字扩展是指增加存储器中字的数量,而位数不变

  • 共用地址线 出现的问题:使得两个芯片同时开始工作

如下图所示

mark

  • 解决方法:如下节所示
    • 线选法 : n条线 产生n个片选信号
    • 译码片选法 : n条线 产生2^n个片选信号

线选法结果:

mark

译码片选法 :

  1. 单位二进制片选

mark

  1. 多位二进制位的片选

mark

译码片选法结果 :

地址空间分布

  • 00XX
  • 01XX
  • 10XX
  • 11XX

mark

小结:

mark

4.1.3 字和位同时扩展

  • 先进行位扩展
  • 再进行字扩展

mark

5. 双端口RAM和多模块存储器

5.1 双端口RAM

  • 双端口RAM 设计思路:同一个存储器有左右两个独立的端口,分别具有两组相互独立的地址线,数据线和读写控制线
  • 允许两个独立的CPU同时异步的访问存储单元

mark

  • 缺点:CPU可能再对同一地址单元,会因数据的冲突造成数据存储或者读取错误
    • 解决方法:使用忙信号

mark

5.2 多模块存储器

  1. 单体多字存储器:只有一个存储体,每个存储单元存储m个字,总线的宽度也为m个字

mark

  1. 利用存储周期中:存储体需要对电信号进行恢复的特点可以分为:
  • 高位交叉编址
  • 低位交叉编址

对于连续访问地址而言:

  • 高位交叉编址:不能提高存储的吞吐率

mark

mark

  • 低位交叉编址:可以提高存储的吞吐率
    • 采用流水线的存取方式
    • 连续存储m个字的存储时间为:t = T + (m - 1)r
      • T 是一个存储周期
      • m是存储字
      • r是总线的传输周期

mark

mark

小结:

mark

5.3 小结

mark

6. 高速缓冲存储器

前言:使用高速缓存的原因

  • 使用并行的多模块存储器之后 : CPU和存储器的速度差距依旧很大
  • 这就必须改变存储的体系:Cache(SRAM)-主存(DRAM)
  • 高速缓存的原理是利用程序访问的局部性原理来实现的

mark

6.1 程序访问的局部性原理分析

  • 程序访问的局部性原理包括
    • 时间局部性 : 最近未来要使用到的信息,很可能是现在使用的信息
    • 空间局部性 : 最近的未来用到的信息,很可能是现在正在使用信息在存储空间上邻近的,因为指令通常是顺序存放的

举个例子:看下面两段代码来判断谁的性能更好?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
### 程序A
int sumarrayrow(int a[M][N]){
int i,j,sum = 0;
for(int i = 0,i < M,i++){
for(int j = 0;j < N;j++){
sum += a[i][j];
}
}
return sum;
}

### 程序B
int sumarrayrow(int a[M][N]){
int i,j,sum = 0;
for(int j = 0,j < N,i++){
for(int i = 0;i < M;j++){
sum += a[i][j];
}
},
return sum;
}

// 假设M和N都是2048,按字节编址的话,每个元素占用4个字节
对于程序A来说 ,对数组的访问是a[0][0],a[0][1]...a[0][2047],a[1][0]...a[1][2047],访问顺序和存放的顺序是一致的,因此空间局部性较好

对于程序B来说,对数组的访问是a[0][0],a[1][0]...a[2047][0],a[0][1],a[1][1]...a[2047][1],若主存与Cache的交换单位小于8KB,则访问每一个元素都需要装入一个主存块到Cache中,因此没有空间局部性

对于时间局部性来说,两个数组的元素都只被访问了一次,因此时间局部性较差。

对于for循环来说,程序A和程序B的时间局部性和空间局部性都较好,都被执行了2048*2048

在电脑上进行试验,两个程序的所需的时钟周期相差了21

6.2 Cache 的工作原理

  • Cache 位于存储器结构的顶层,通常是由SRAM组成
  • Cache 块又被叫做Cache 行,每块由若干字节组成,块的长度叫做行长
mark

工作过程

  • 当发出读请求时
    • 若访问的地址在Cache 命中,就将地址转换成Cache 地址,直接对Cache 进行操作,与主存无关
    • 若访问的地址在Cache 未命中,就访问主存,同时将此字所在的块一次调入到Cache 中
    • 若此时Cache 已满,则需要使用你某种替换算法,用这个块替换Cache 中原来的某块信息
  • 当发出写请求时
    • Cache 命中,有可能遇到的Cache 与主存中的内容不一致的问题
      • 由于CPU写Cache 。把Cache 中的内容从X改为了Y,而主存中的数据依旧是X
    • Cache没有命中,按照一定的写策略处理,常用的方法是全写法和写回法

注意:

  • Cache 和CPU交换数据是使用字节为单位
  • 而Cache 和主存之间的交换数据是使用Cache 块为单位

举个例子:

  • 未命中的时候: 从主存拉数据

mark

  • 未命中的时候:从cache拉数据,再访问主存

mark

小结:

mark

6.3 Cache和主存的映射方式

  • Cache 会有如下问题的存在
mark
  • 首先我们来看如何将主存的内容存入到Cache中
    • 直接映射 : 对号入座
    • 全相联映射 :全相联映射
    • 组相联映射 :组内随意放,按号分组

举个例子:待后续具体分析

mark

6.3.1 全相联映射

  • 主存中的每一块放到Cache 中的任意位置
  • 优点:空间命中率高,利用率也高
  • 缺点:标记速度慢,成本高

mark

mark

6.3.2 直接映射

  • 主存中的每一块只能装入Cache 中的唯一位置
  • 若这个位置已经有内容,那么产生块冲突,原来的块将无条件的被替换出去(无须替换算法)
  • 直接映射的关系为 j = i mod 2^c
  • 标记不需要标记行号

mark

mark

6.3.3 组相联映射

  • 将Cache 空间分成大小相同的组
  • 主存的一个数据块可以装入一组内的任何位置
    • 组间采用直接映射
    • 组内采用全相联映射

mark

mark

小结:

mark

6.4 Cache 的替换算法

  • 四种算法预览:
mark

举个例子:

  1. 使用全相联映射

mark

  1. FIFO 内存置换
  • 最先调入的是4号块,替换Cache 的第0块
mark
  1. LRU 内存置换
  • 最近最少使用的是12号块,替换Cache的第二块
mark
  1. LFU 内存置换
  • 4号块使用了3次,6号块使用了两次,其他几块均使用了1次,需要更多的依据

小结:

  • 具体的Cache命中率需要考虑
    • Cache的映射算法
    • Cache的替换算法

6.5 Cache 体系结构

mark

6.6 Cache 与主存的 数据不一致

  1. 写策略 - 命中的情形
  • 写回法:当CPU对Cache 写命中的时候,只修改Cache 的内容,而不立即写回到主存中,只有当此块被换出的时候才写回主存。这种方法减少了访存的次数,但存在数据不一致的隐患。
    • 采用这种策略,每个Cache行需要设置一个(脏位),以反映是否被CPU修改过
  • 全写法:当CPU对Cache 写命中的时候,将数据同时写入到Cache 和主存中,当某一块需要替换的时候,不必把这一块写回主存,用新调入的块直接覆盖即可。
    • 优点:实现简单,能随时保证主存数据的正确性
    • 缺点:增加了访存的次数,降低了Cache的效率
    • 一般要设置 : 写缓冲(减少主存和CPU之间的损耗)
    • 写缓冲有可能会溢出

mark

  1. 写策略:不命中的情形
  • 写分配法:未命中时,将主存数据调入到Cache中,然后更新这个Cache块,同时搭配写回法

mark

  • 非写分配法 : 直接改写主存,搭配全写法

小结:

mark

  • 现代计算机一般使用多级Cache, 如下图所示:

mark

  • L1 Cache 和 L2 Cache 之间使用全写法,L2 Cache 对主存使用写回法

mark

6.7 虚拟存储器

mark

  • 主存和辅存共同构成了虚拟存储器

    • 对于程序员而言,虚拟存储器是透明的
    • 相当于对实体存储器进行了一层封装
  • 虚拟存储器将主存和辅存的地址空间统一编制,形成一个庞大的地址空间

    • 用户编程允许的地址位:虚地址或者逻辑地址
    • 实际的主存单元被称为:是地址或者物理地址
    • 实地址对应的是主存空间地址
  • CPU使用虚地址时,由辅助硬件找出虚地址和实地址之间的对应关系,并判断这个虚地址对应的存储的那元是否已装入到主存中

    • 若已在主存中,则通过地址变换,CPU可以直接的访问主存的实际存储单元
    • 若不在主存中,则把对应的一页或者一段调入到主存后再由CPU访问
    • 若主存已满,则采用替换算法替换主存中的一页或者一段

以下只是简单介绍,具体看操作系统的博客内容

6.7.1 页式虚拟存储器

  • 虚拟空间和主存空间都被分为大小相同的页,主存的页叫做实页,虚拟的页叫做虚页
  • 虚拟地址分为两个字段:
    • 虚页号
    • 页内地址
  • 虚拟地址和物理地址的转换通过页表来实现
  • 页面的大小是固定的

mark

例题:

mark

6.7.2 段式虚拟存储器

mark

  • 段的长度是可变的,段表只需要给出各段的起始地址和段的长度
  • 优点:段的分解与程序的自然分界相对应,易于编译
  • 缺点 :长度可变

6.7.3 段页式虚拟存储器

  • 先将程序按逻辑分段,每段再划分称为固定大小的页
  • 虚地址分为 段号 + 段内页号 + 页内地址
  • 缺点是:变换过程中需要多次查表,系统开销较大

6.7.4 快表

  • 页表,段表存放在主存中,收到虚拟地址后需要先访问主存,查询主存中的页表,段表叫做慢表
  • 快表的思想:利用高速缓存存放页表项
  • 利用局部性原理存入Cache

6.7.5 小结

mark

打赏
  • 版权声明: 本博客所有文章除特别声明外,均采用 Apache License 2.0 许可协议。转载请注明出处!
  • © 2019-2022 Zhuuu
  • PV: UV:

请我喝杯咖啡吧~

支付宝
微信