更新于 

高性能存储器

双端口RAM

为了提高CPU访问存储器的速度,可以采用双端口存储器、多模块存储器等技术,它们同属并行技术,前者为空间并行,后者为时间并行,这里我们先来学习双端口存储器。

双端口RAM是指同一个存储器有左、右两个独立的端口,分别具有两组相互独立的地址线、数据线和读写控制线,允许两个独立的控制器同时异步地访问存储单元,如下图所示。

很明显当两个端口的地址不同时,在两个端口上进行读写操作一定不会产生冲突。但是,两个端口同时存取存储器的同一地址单元时,会因数据冲突造成数据存储或读取错误。两个端口对同一主存操作有以下4中情况:

  1. 两个端口对不同时对同一地址单元存取数据(无冲突)
  2. 两个端口同时对同一地址单元读出数据(无冲突)
  3. 两个端口同时对同一地址单元写入数据(存取数据)(有冲突)
  4. 两个端口同时对同一地址单元,一个写入数据,另一个读出数据(有冲突)

因此后两者对同一地址单元的操作会有冲突(情况3写错误,情况4读错误),此时操作就不能并行进行。我们要避免后两者情况,做法是设置忙信号为0,由判断逻辑决定暂时关闭一个端口(即被延时进行),未被关闭的端口正常访问,被关闭的端口延长一个很短的时间段后再访问。

多模块存储器

提高CPU访存速度,常采用多模块存储器,常用的有单体多字存储器和多体低位交叉存储器。CPU的速度比存储器的的快,因此如果一条一条指令的读取,会有很长的等待时间,因此考虑同时从存储器中取出n条指令,就可以充分利用CPU资源,提高运行速度,多体交叉存储器就是基于这种思想提出的。

单体多字存储器

单体多字系统的特点是存储器只有一个存储体,每个存储单元存储m个字,总线宽度也为m个字,这样一次访问一个存储单元就相当于并行读出m个字,因此地址必须顺序排列并处于同一存储单元。

单体多字存储系统在一个存取周期内,从同一地址取出m条指令,然后将指令逐条送至CPU执行,每隔1/m存取周期,CPU向主存存取一条指令。显然这增大了存储器的带宽,提高了单体存储器的工作速度。

但是缺点是指令和数据必须是连续存放的,一旦遇到了转移指令,或者操作数不能连续存放,这种方法的效果就很不明显。

多体并行存储器

多体并行存储器由多体模块组成,每一个模块都有相同的容量和存取速度,各模块都有独立的读写控制电路、地址寄存器和数据寄存器。他们既能并行工作,又可以交叉工作。

多体并行存储器又分为高位交叉编址(顺序方式)和低位交叉编址(交叉方式)两种。

高位交叉编址

高位交叉编址中高位地址表示体号(即模块号),低位地址为体内地址(即模块内偏移地址)。如下图:

存储器共有4个模块M0~M3,每个模块都有n个单元,各模块地址的范围如图中所示。那么在高位交叉编址方式下,总是把低位的体内地址送到由高位体号决定的模块内进行译码。访问一个连续主存块时,总是先在一个模块内访问,等到该模块访问完才可以转到下一个模块访问,CPU总是按顺序访问存储模块,存储模块不能被同时并行访问,因而不能提高存储器的吞吐率。我们来思考一下上面这种方式的运行特点:

首先我们知道地址是连续的,所以地址应该为00001,00010,00100…~01001,前两位是高位体号,后三位是体内地址。那么对于每一个地址的读取都是先看体号再根据体内地址进行一个存储单元的存取。那么也就是说对于上面的地址,依次是先将M0模块内的每一个存储单元进行顺序的存取以后才开始对M1进行存储单元的存取,同样M1内的所有存储单元全部存取完以后才会进行M2的。并且此时模块内没有并行进行,即每一次只有一个模块在进行对存储单元的存取。我们假设对于任何一个模块内的存取单元的存取周期都是T,那么对于任何一个模块内,都是顺序对存储单元进行存取,所以任意一个模块的存取时间是nT,又因为有4个模块,所以上图的4个模块全部执行完需要4nT。因为此时任意一个存储单元只存储一个字,所以我们可以知道对于顺序方式读取m个字需要顺序访问m个存储单元,所以时间是mT。

一定要注意模块内的地址是连续的,存取方式仍是串行的,因此这种存储器仍然是顺序存储器。

低位交叉编址

低位地址为体号,高位地址是体内地址。如下图:

那么此时每个模块按“模m”交叉编址,即模块号=单元地址%m,假定有m个模块,每个模块有k个单元,则0,m,…,(k-1)m单元位于M0,第1,m+1,…,(k-1)m+1单元位于M1,以此类推。

在低位交叉编址方式下,总是把高位的体内地址送到由低位体号确定的模块内进行译码。程序连续存放在相邻模块中,因此采用此编址方式的存储器为交叉存储器。采用低位交叉编址后,可在不改变每个模块存取周期的前提下,采用流水线的方式并行存取,提高存储器的带宽。原理如下:

设模块字长等于数据总线宽度,模块存取一个字的存取周期为T,总线传送周期为r,那么我们知道这种方式的存取,不是一次性将一个模块全部操作完,而是先将各个模块的相对同位置的体内偏移进行操作,所以每一次存取操作都会切换模块及为M0M1M2M3M0M1M2M3这种方式,所以当M0得到了数据总线传来的数据就可以自己进行相对应的存取操作了时间为T,而此时存取操作不会停止等待,因为他可以立刻切换到下一个模块,对下一个模块的存储单元进行操作,只是需要等待下一个数据从数据总线传来的时间r,所以会延迟一个r,所以对于一个T,可以包括许多个r。我们定义m=T/r,m称为交叉存取度。每次经过r时间延迟后启动下一个模块,交叉存储器要求其模块数必须大于等于m,这样就可以保证启动某模块后经过m×r的时间后会再次启动该模块时,其上次的存取操作已经完成(这样就实现了流水线不间断)。所以存取m个字所需要的时间就大大缩短成了T+(m-1)r比高位交叉编址的mT快了许多。

究其原因是因为此时多个模块可以并行执行存取操作了,如上图一个T,4个模块都可以开始进行自己的任务了,而无需待前者必须完成操作才能开始,这就是流水线原理。

思考:流水线时间图一定是上面的样子吗?

不一定,上面这个刚好是m=T/r=C(C时正整数)时的图,当m小于T/r时会出现第一个模块还没有执行完就又轮到第一个模块进行下一个数据的操作了,那么就需要有等待了。即上图中的W4灰块左移一点点即为这种情况。当m大于T/r时,那么第一个模块执行完以后还需要再等待一小段时间才会再次轮到他工作。即为上图中的W4灰块右移一点点的情况。所以当m=T/r=C时是最理想的流水线情况,如果不能做到,那么有一小段时间延迟也没有关系。

例题

设存储容量为32个字,字长为64位,模块数m=4,分别采用顺序方式和交叉方式进行组织。存储周期T=200ns,数据总线宽度为64位,总线传输周期r=50ns。在连续读出4个字的情况下,求顺序存储器和交叉存储器各自的带宽。

首先无论是哪种存储方式读出m=4个字的信息总量都是

q=64×4=256q=64位×4=256位

顺序存储器连续读出4个字所需要的时间是

t1=mT=4×200ns=800ns=8×107st_1=mT=4×200ns=800ns=8×10^{-7}s

而交叉存储器读出4个字所需要的时间是

t2=T+(m1)r=200ns+3×50ns=350ns=35×108st_2=T+(m-1)r=200ns+3×50ns=350ns=35×10^{-8}s

所以带宽分别是

{顺序存储器:W1=q/t1=256/(8×107)=32×107b/s交叉存储器:W2=q/t2=256/(35×108)=73×107b/s\begin{cases}顺序存储器:W_1=q/t_1=256/(8×10^{-7})=32×10^7b/s\\交叉存储器:W_2=q/t_2=256/(35×10^{-8})=73×10^7b/s\end{cases}

所以交叉存储器的带宽更大,效率更高。一个存储周期内,交叉存储器可以提供的数据量为单个模块的m倍。

总结