存储系统

存储器的分类

相联存储器 是按内容指定方式和地址指定方式结合来进行寻址的存储器。
双端口存储器 是具有两套独立读/写口,且具有各自地址寄存器和译码电路的存储器,可以同时访问同一区间、同一单元(都进行读操作时,则不会产生冲突)。

性能指标

  • 存储容量:存储容量=存储字数×字长,例如:1M×8位。
  • 单位成本:每位价格=总成本/总容量
  • 存储速度:数据传输率=数据宽度/存储周期

存储速度

  • 存取时间TaT_a:从启动一次存储器操作到完成此操作所经历的时间,分为读出时间和写入时间;
  • 存取周期TmT_m:存取周期又称读写周期或访问周期。指进行一次完整的读写操作所需要的全部时间,即连续两次独立的读/写操作之间需要的时间
  • 主存带宽BmB_m:主存带宽又称数据传输率,即每秒从主存进出信息的最大数量。

存取时间不等于存取周期,通常存取周期大于存取时间
这是因为读写操作后,总是需要一段时间进行内部恢复,对于破坏性读出存储器,存储周期往往比存取时间大得多,因为信息读出后需要马上再生

存储器从快到慢的排列顺序是:
寄存器、Cache、主存、辅存

RAM & ROM

随机存储器

主存储器由 DRAM 实现,靠处理器的那一层(Cache)则由 SRAM 实现。它们都属于易失性存储器,只要电源切断,所保存的信息将丢失。

若操作系统保存于硬盘中,则主存除了 RAM 以外,还需要 ROM 参与构成。
因为硬盘内的操作系统需要 BIOS 引导程序引导到主存中,而引导程序应该固化于不易失性的存储器 ROM 中。

  • SRAM , Static. 称为静态随机存储器。其存取速度快但集成度低,价格昂贵,所以一般用于 Cache
  • DRAM, Dynamic. 称为动态随机存储器。其容易集成,位价低,容量大。

由于 DRAM 芯片容量较大,地址位数较多,为了减少地址引脚数,通常采用地址引脚复用技术,行地址和列地址通过相同的引脚分先后两次输入,这样地址引脚数即可减少一半

DRAM 通过存储元电路中栅极电容上的电荷进行信息的存储,但是一般只能维持 1 到 2ms 的时间,所以若不做处理将极易丢失数据。为此,应当对其每隔一段时间就进行一次刷新。主要的刷新方式有:

  1. 集中刷新。每个一段固定时间(刷新周期,也称“死时间”)就按进行逐一再生;
  2. 分散刷新。对每行的刷新分散到不同的工作周期里,前半部分周期用于读写,后半部分用于再生;
  3. 异步刷新。将刷新周期除以行数以得到两次刷新操作之间的时间间隔τ\tau ,通过逻辑电路定时刷新,可缩短“死时间”

注:刷新不需要选片,整个存储器的所有芯片是同时被刷新的。

注:集中刷新有“死时间”,异步刷新只是缩短了“死时间”,而没有“死时间”的刷新策略是分散刷新。

只读存储器

只读存储器 ROM 结构简单,因此位密度比RAM高,具有非易失性,可靠性高。

根据制作工艺不同,ROM 还可分为掩模式只读存储器(MROM)一次可编程只读存储器(PROM)可擦除可编程只读存储器(EPROM)Flash存储器和固态硬盘(SSD).

引脚数问题

若已知某存储器芯片的容量2m×n2^m\times n

  • 其中的nn 就是每个单元数据的位数,所以需要nn数据线
  • 其中的2m2^m 为地址个数,因为有地址译码器的作用,所以并不需要2m2^m 条地址线;在二进制中,log22m\log_22^m 位的二进制数就可以用来表示地址编号了,所以只需要地址线mm 条。
  • 此外,若题目没有说明,默认还有一条片选线,两条读写控制线(读控制 RD、写控制 WD)。

最终,所需引脚数为:n+m+1+2n+m+1+2.

注:读写控制线也有可以共用一条,从而引脚数是n+m+1+1n+m+1+1
如果是选择题,并且题干中没有指出这种可能,那么一般也不会两种情况都在选项中。

注:一定要注意 DRAM 芯片的地址引脚数因为复用技术而减半,所以引脚数在 DRAM 的情况下,应该为:n+m/2+1+2n+m/2+1+2n+m/2+1+1n+m/2+1+1 .

此细节曾被多次作为考题进行考察,应当多加小心。


并行主存系统

并行主存系统是在一个访存周期内能并行访问多个存储字的存储器。运用这种技术的存储器也被称为多模块存储器

首先我们来考虑 单体单字宽的存储器,即字长与 CPU 的字长相同的存储器。
因为它每一次只能访问一个存储字。假设该存储器的访问周期是TmT_m,字长为ww 位,则其带宽为:

Bm=wTmB_m=\frac w{T_m}

为了提高存储器的带宽,提出了下面两种并行存储器结构:

  1. 单体多字存储器
  2. 多体交叉存储器

单体多字存储器

单体多字存储器,顾名思义,只有一个“体”,即此系统下只有一个存储器。若每个存储单元存储mm 个字,总线长度也为mm 字,则单体多字存储器能够在每个存储周期内一次读出mm 个字。
因此其最大带宽提高到原来的mm 倍。即Bm=m×w/TmB_m=m\times w/T_m.

缺点:要求指令和数据在存储器内部是连续存放的,否则一旦遇到转移指令或操作时不能连续存放,该方法就基本退化了。

多体并行存储器

多体并行存储器由多体模块组成。每个模块都有相同的容量和存储速度,各模块又各自有独立的读写控制电路、地址寄存器和数据寄存器。它们可以并行工作,也能交叉工作。
多体并行技术就是利用了多个模块的交叉工作,从而改善存储器性能。可范围两种交叉方式。

高位交叉编址 |顺序方式

高位交叉编址利用高位地址来表示体号(即存储体的编号),用地位地址来指示体内地址。如下图所示。

高位交叉编址结构图

该图给出了适合于并行工作的高位交叉编址的多体存储器结构。按这种编址方式,只要合理调动,使不同的请求源同时访问不同的体,便可实现并行工作。例如,当一个体正与 CPU 交换信息时,另一个体可同时与外部设备进行直接存储器访问,实现两个体并行工作。

但是,访问一个连续主存块时,总是先在一个模块内访问,等该模块访问完毕只后才访问下一个,即 CPU 总是按照顺序访问存储体,所以这种存储器仍然是顺序存储器。

因为高位交叉存储器在单个存储器中的字是连续存放,所以不满足程序的局部性原理
而下面介绍的低位交叉存储器则很好地满足局部性原理

低位交叉编址 |交叉方式

低位交叉编址规定低位地址为体号,高位地址为体内地址。不仅如此,每个模块还按照 “模mm ”交叉编址,即模块号 = 单元地址 % m.
例如,总共有mm 个模块,每个模块有kk 个单元,则0,m,,(k1)m0,m,\cdots,(k-1)m 单元存放在模块M0M_0 中,1,m+1,,(k1)m+11,m+1,\cdots,(k-1)m+1 单元存放在模块M1M_1 之中,以此类推。如下图所示。

地位交叉编址结构图

可见,此种结构及其对应的交叉编址方式,使得程序连续存放在相邻的模块中,所以我们能在不改变存取周期的前提下,采用流水线的方式进行存取,以提高存储器的带宽。

设模块字长等于数据总线的宽度,模块存取周期为TmT_m,总线的传送周期为rr,为了实现流水线存取,存储器的交叉模块个数mm满足mTm/rm\geq T_m/r.

因每隔rr 的时间,就会存取下一模块的内容,所以连续存取xx 个字,所需的时间为:

t=Tm+(x1)rt=T_m+(x-1)r

考察整体工作性能

采用低位交叉编址时,我们知道,连续存取xx 个字,所需的时间为:t=Tm+(x1)rt=T_m+(x-1)r
所以平均每一个字的存取时间应该是t/xt/x,即:

Tm+(x1)rx\frac{T_m+(x-1)r}{x}

而在实际工作时,连续存取的字的数量xx 是很大的,所以每个字的平均存取时间会逐渐趋于总线周期rr,即:

limx+Tm+(x1)rx=r\lim_{x\to+\infty}\frac{T_m+(x-1)r}{x}=r

所以,在评价工作性能时,我们把总线周期rr 作为一个字的平均读取时间。这也说明,在一个存取周期TmT_m 中,存储器能向 CPU 提供mm 个字大小的数据。(此处mm 既是交叉模块数,也是一个存取周期内能提供的字的数量)

还可以从流水线的角度出发,当流水线运行起来的时候,没有源头没有结尾,从中间任取xx 个字,考察其存取时间时,该时间正好是流水线图上的xx 个台阶大小,即总线周期长度。

试分析多端口存储器和多体结构存储器的优缺点(见王道计组100页)

访存冲突问题

前面我们提到,若连续读取数据字,则低位交叉存储器可以达到很好的效果。所以这就依赖于访存的数据地址是否满足低位交叉存储器的模块划分规则,即 mm 交叉编址

如某计算机采用四位交叉编址存储器,存储器在总线上出现的主存地址序列(十进制)为 8005、8006、8007、8008、8001、8001、8003、8004、8000。我们每一个地址都做模4运算,即可得到这些地址分别存放在模块号为几的存储模块中。

若访问模块的序列满足流水线那样的循环节规律,则说明没有发生访存冲突。否则,相邻四次访问中出现在同一个存储模块内,则说明发生了访存冲突。
显然,上述序列中,只有 8004 和 8000 都属于模块号为 0 的存储体,所以它们是一对访存冲突对

  1. 计算磁盘数据传输率、平均查询扇区时间(一圈的时间/2)、平均存取时间=寻道+查扇+信息延迟+读取,其中读取=读取大小*单位大小所需时间=读取大小/传输速率
  2. cache的命中率、平均访问时间、访问效率问题

磁盘

  1. 磁盘按块存取
  2. 磁盘格式化后的容量比非格式化容量要小
  3. 寻道时间和旋转延迟时间通常取平均值参与计算
  4. 数据传输率Dr=rND_r=rN,式中rr 为磁盘转速,NN 为每条磁道容量大小
  5. RAID 是独立冗余磁盘阵列
    • 同时使用多个磁盘,可以提高传输率;
    • 多个磁盘并行存取,可以提高数据吞吐量;
    • 通过镜像功能,可以提高安全可靠性;
    • 通过数据校验,可以提高容错能力。

高速缓存

Cache 一般 由 SRAM 组成。

局部性原理

  • 时间局部性 一旦一条指令执行,它就有可能在不久的将来再执行
  • 空间局部性 一旦一个存储单元被访问,它附近的存储单元也可能很快就被访问

CPU 欲访问的信息已在 Cache 中的比率 称为 Cache的命中率HH.

H=NcNc+NmH=\frac{N_c}{N_c+N_m}

式中,NcN_c —— Cache 的总命中次数;NmN_m —— 访问主存的总次数

Cache-主存系统的 平均访问时间TaT_a

Ta=Htc+(1H)tmT_a=Ht_c+(1-H)t_m

式中,tct_c——命中时 Cache 的访问时间;tmt_m 未命中时的访问时间

Cache-主存映射方式

Cache块中存储的是主存中的一个副本,因为其行数比主存块(把主存按照Cache块的大小进行划分)少,所以主存往往只有一部分块的信息被拷贝到Cache中。
而为了指明Cache中的数据来自主存地址中的哪一部分,常常需要通过 地址映射 进行指示,其中标记位 Tag 尤为重要。
所以,一个Cache块中的内容最主要由以下两个部分组成:

标记阵列数据 (DataData)
位数与映射方式和写策略有关位数与Cache块自身的逻辑容量有关

在标记阵列中,一定有用于识别主存地址的 Tag,还有用于判断有效情况的有效位。
此外,根据 Cache写策略 的不同, 还会附加:替换控制位、脏位 等。

直接映射

主存中每一个块的内容只能装在 Cache 中的唯一一块中。该映射方法实现简单但不够灵活,空间利用率低。
其示意图如下:

Cache 的直接映射方式

定义:j=imod2cj = i \mod 2^c
其中,jj 表示CacheCache 的块号(行号),ii 表示主存的块号2c2^c 表示CacheCache行数.

这里,主存块的大小与一个cache块的大小是相等的.

  • 如果一个 Cache 块的容量为2bB2^bB,按字节编址,那么 块内地址 应占log2(2bB/B)=b\log_2(2^bB/B)=b 位。
  • 如果主存地址nn 位,那么主存块的个数为2n/2b2^n/2^b,记为2m2^m . 所以 主存块号iilog22m=m\log_2 2^m=m 位。

从而根据公式可以直接推导出如下的映射表(标记阵列) 及其与主存地址(记为AA ) 所对应的内容:

标记 (TagTag)行号jj (IndexIndex)块内地址 (OffsetOffset)
AA 的高ttAA 的中间ccAA 的低bb

🎲注意 映射表是一个逻辑概念,是计算机通过该映射逻辑进行数据存取的直观展现。
在计算Cache的总容量时,我们需要计算的是标记阵列+数据

值得注意的是,标记阵列中只有Tag是与映射表一样的,此外还有1位有效位,以及根据写策略判断是否加入脏位(也叫一致维护位,采用写回法时需要增加脏位)。
(若题目要求,还需考虑替换算法的替换控制位

全相联映射

主存中每一块都可以装入Cache中的任何位置。每行的标记 Tag 用于指示该行取自主存的哪一块。

由于每一块可以是任意位置,所以全相联映射也不再需要行号这个标记,所以他的映射表只有 tag 和 块内地址 两项。示意图如下:

Cache 的全相联映射

最后给出全相联映射的映射表:

标记 (TagTag)块内地址 (IndexIndex)
AA 的高nbn-bAA 的低bb
该内容既是映射表 Tag 也是主存块号ii该内容既是主存块的块内地址,也是cache块的块内地址

注:其中的bb 与直接映射中的bb 相同,由Cache本身决定。下面介绍的组相联映射也一样。

注:全相联映射 的 cache地址 不一定是取AA 的低b+cb+c 位,因为其随机性,块号需要单独指定。

组相联映射

将 Cache 空间分为大小相等的QQ 个组,每组有rr 行,组内数据块采用全相联映射方式,组间采用直接相联映射方式,这样的地址映射方法就被称为rr组相联映射。
其中有:

Q=2cmodrQ=2^c\mod r

Q=2cQ=2^c ,即r=1r=1时,组相联映射就变成了直接相联;
Q=1Q=1,即r=2cr=2^c 时,就变成了全相联。

下面给出一个二路组相联映射的 Cache 示意图:

二路组相联映射

定义j=imodQ=imod(2cmodr)=(imod2c)modrj=i\mod Q=i\mod (2^c\mod r)=(i\mod 2^c)\mod r
注意,此处的jj 是组号而不再是行号了。

  • 如果分组过程中,每组有r=2cr=2^c 行,那么 组号jj 的位数即是log2r=log22c=c\log_2 r=\log_2 2^c=c 位。

映射表及其与主存地址(记为AA ) 所对应的内容:

标记 (TagTag)组号jj (IndexIndex)块内地址 (OffsetOffset)
AA 的高mcm-cAA 的中间ccAA 的低bb

其中,块内地址,即 A 的低 b 位中的高log2r\log_2 r 位是该存储块在第jj 组的块号。

Cache-写策略

因为 Cache 是主存的副本,所以当 Cache 的内容修改时,需要选用合适的写操作策略使得二者内容最最终保持一致。

对于 Cache 的写命中(Write Hit)有两种处理方法。

  1. 全写法(写直通法、write-through)。把数据同时写入 Cache 和主存中。该方法增加了访存次数,降低了 Cache 的效率;为减少时间损耗还可以加入写缓冲Write Buffer)这种 FIFO 队列解决速度匹配问题,但是频繁写入也会造成缓冲区的饱和溢出。
  2. 回写法write-back)。每个 Cache 行设置一个脏位(修改位),替换回内存时通过脏位决定是否写回内存。

对于 Cache 的写不命中,也有两种处理方法。

  1. 写分配法write-allocate),通常和回写法配合使用。要求写内容时从 Cache 中写,若没有调入 Cache 则先从主存中调取。此方法尝试利用程序的局部性,但是每次不命中都要读取一块内容。
  2. 非写分配法not-write-allocate),通常和全写法配合使用。只写入主存,不写入 Cache。

虚拟存储