计算机组成
8 存储层次结构
8.1 存储层次结构概况
如果CPU爱好哲学,它可能一直在问自己两个问题。
我要运算的数据从哪里来?我算完的数据又将去向哪里?
这在计算机世界当中确实是一个非常重要的问题。这也正是我们今天所要探讨的主题:存储器。
这是我们非常熟悉的冯·诺依曼计算机结构,这其中哪些部件和存储功能有关呢?存储器自然会是一个,而外部记录介质也是带有存储功能的,这两个都比较明显。
另外还有一个也带有存储功能那就是运算器。因为CPU当中的通用寄存器是包含在运算器当中的,通用寄存器中也是用来存放临时的数据,也可以看作是一种存储器。
这些就是我们要介绍的构成存储层次结构的主要部件,为了便于描述把这些部件都统称为存储器。
那我们来看一看计算机当中对存储器有哪些需求。
首先存储器当中应该保存了将要运行的程序和需要运算的数据,那这些内容在系统通电启动的时候就应该在存储器当中了,而且在断电之后也不会丢失。那么具有这样特定的存储器我们称之为非易失性存储器。而断电后存储的信息就会丢失的存储器则称为易失性存储器。在现在的计算机系统当中主存和CPU当中的通用寄存器都是易失性的存储器,断电之后其中的信息就丢失了。而bios芯片和硬盘则是非易失性的存储器,所以,在系统通电之后CPU必须要从bios芯片开始执行程序,然后这段程序把硬盘等设备配置好之后再将更多的程序和数据从硬盘搬运到内存,之后CPU才可以在内存里执行程序。因此,在系统中必须要有非易失性的存储器。
第二这样的存储器肯定得是可读又可写的。那在这个结构当中硬盘和主存都是可读可写的,而bios芯片则是一个只读的芯片,倒不是说它完全不支持写操作,而是对它的写需要借助特殊的设备或者特殊的操作过程,非常的麻烦,无法支持经常性地写入数据。
第三存储器最好是能够支持随机访问。所谓随机访问是指对存储器当中任何一个数据的访问所花费的时间与这个数据所在的位置没有关系。一种典型的非随机访问的设备就是磁带,比如早期要听歌都是要使用磁带的,假如现在磁带的开头你就可以马上听第一首歌,但是如果你想听第十首歌,你就得用快进的方式快速的卷过前九首歌才能够听第十首。这样的访问就是和它的位置有关的,而在计算机程序的运行过程中,我们会访问到存储器的任意位置,如果不支持随机访问,这就会对性能造成很大的影响。在这里对主存的读写和bios芯片的读都是支持随机访问的。而硬盘内部实际上是由多个盘片构成,这些盘片处于高速旋转的状态,并由一个机械的读写头去寻找需要访问的数据的位置,这就不是随机访问的模式,而且由于其中有机械部件的存在,速度就变得非常的慢。
而在计算机当中存储器的速度也就是访问的时间也是一个非常重要的因素。CPU的运行速度很快,在它需要访问存储器的时候,最好能在一个时钟周期内就完成数据的访问,不然就会阻碍CPU后续的操作。而主存的速度是明显高于硬盘的速度的。所以,总体看来,如果我们能找到一个存储器支持随机读写而且是非易失性的,访问时间也很短,那么就可以考虑只用这样一个存储器和CPU连接,当然我们还要考虑到是否有足够大的容量以装下所以我们需要的程序和数据,还有价格是否能够承受,以及功耗是否合适等等。
既然现状我们是使用了这么多种不同的存储器,虽然是因为没有一个唯一而完美的解决方案,那么就从性能和价格等方面对它们进行一个比较。
这是30年来具有代表性的CPU。我们每隔十年选取一个代表,80年的8080,时钟频率大约为一兆赫兹,其时钟周期是一千纳秒。90年我们选取了386的一个版本,时钟周期是五十纳秒。而2000年选择的是奔腾二,时钟周期大约为一点六纳秒。2010年选择的是Core i7,时钟周期大约是0.24纳秒,当然我们要注意因为这个时候已经是四核了,如果每个核,每个时钟周期都需要对外传输数据,那其实相当于每零点一纳秒就需要传输一个数据。那么就以这个CPU的时钟周期为指标来看一看外部存储器的特性。
首先我们来看硬盘。硬盘的访问时间在80年的时候大约是87,我们注意这个单位是毫秒。毫秒和纳秒差了一百万倍,所以,虽然这30年来硬盘的访问速度也有所提升,大概提升了29倍,但它和CPU的时钟周期完全没有可比性,相差数百上千万倍。所以,仅从访问时间这一项来看硬盘从一开始就不具备直接和CPU进行交互的能力。当然它的优势在于容量大而且便宜。在80年的时候大约每兆字节需要五百美元,那时典型的硬盘容量是一兆字节。而在这30年中硬盘单位容量的价格在迅速的下降,下降幅度超过160万倍。而与此同时硬盘的容量也在迅速的增长,上升的幅度也有150万倍。这样我们就可以存放更多的程序和数据。这是硬盘技术进步带来的最大的好处。当然另外还有一件很有意思的事情,我们发现价格下降的幅度和容量上升的幅度基本相当,也就是说现在和30年前相比虽然硬盘的容量和单个字节的价格有了巨大的变化,但是整个硬盘的价格却基本保持着不变。那好硬盘作为一个非易失性的存储器自然有它自己的作用,但是要想和CPU直接交互还得看其他的设备,这就是DRAM。
现在的主存主要是采用DRAM实现。它的访问时间在1980年大约是375纳秒,我们注意到这个时候DRAM实际上比CPU的运行的速度还要快一些。所以,这时候并不用担心内存无法及时给CPU提供数据的事情。而到了90年DRAM的速度已经比CPU的速度慢了,而且后来这个差距越来越大,到2010年,即使只考虑单核CPU的需求,DRAM的访问时间也和CPU的时钟周期相差一百倍。在这同样的这30年里CPU的时钟频率提升了2500,而DRAM的访问速度却只提升了9倍。所以,这个差距明显是在拉大的。不过DRAM的进步也同样体现在其容量和价格上,这30年来其容量足足提升了有12万倍之多,而成本也几乎有同样比例的压缩,也就是说我们可以与30年前用同样的价格买到12万倍的容量的内存。容量扩大自然是一件好事,但是这个性能的差距到底会带来什么样的影响呢?
我们通过一个例子来看一看。假设CPU直接连接着DRAM构成的主存,那在CPU当中执行一条指令所需要花的时钟周期大约是这样的。我们就以奔腾CPU执行指令的五个步骤为例,首先是取指,我们假设在CPU内部需要花一个周期产生访问存储器的地址,那么接下来就因为要读存储器而进行等待,所以这样CPU就会等待一百个时钟周期才能得到这条指令的编码,然后再花一个周期在CPU内部进行译码。第三步在奔腾当中是生成地址。第四部则是执行。如果在执行当中需要去访问存储器读取操作数,那又需要再等待一百个周期,然后才可以得到操作数,并在CPU内部再用一个周期完成相应的执行工作。最后花一个周期写回到寄存器,但是如果目的操作数是存储器的话那还需要花一段时间完成写存储器的操作。那么这里就可以看到实际上执行一条指令大约要花掉二百多个时钟周期,而且绝大多数的时间都在等待存储器。我们原先希望一个时钟周期就能完成一条指令,那如果CPU真是这么运行的,那一个1G赫兹的CPU只相当于时钟主频只有5兆赫兹的CPU的性能了。这样显然是无法接受的。所以,我们必须要考虑如何提升CPU访问存储器的性能。
既然DRAM的性能提升有限,就只能去寻找其它速度更快的存储器。比如说SRAM就是一种选择。可以考虑在CPU和DRAM之间,加上一个速度更快的SRAM,如果我们能让CPU所需要的程序和数据大部分时间都存放在这个SRAM当中,那CPU就可以获得快得多的存储器访问时间。这样一个SRAM的部件,就称为cache,也就是高速缓存。那我们来对比一下cache对指令执行时间的影响,SRAM的访问时间大约可以认为是3个时钟周期,那上面这个指令执行的过程就会变成这个样子,所有读存储器的100个时钟周期都会缩短为大约3个时钟周期,这样大约只需要总共10个时钟周期就可以完成一条指令了。相比于之前的性能,有了巨大的提升。
既然SRAM这么好,那么为什么不用SRAM作为主存呢?
要回答这个问题,我们还得来看这张表。我们再加上SRAM的相关参数。在1980年,SRAM的访问时间大约是300纳秒,比DRAM要快一些,但是很有限,基本上属于相当的访问时间。但是SRAM的访问速度提升的很快,三十年间提升了大约两百倍,而这段时间,DRAM只提升了九倍。在很长一段时间内,SRAM的访问时间与CPU的时钟周期基本相当,所以在之前学习处理器结构的过程中,我们一直认为CPU可以在一个时钟周期内从高速缓存当中获得数据,即使在2010年的时候,SRAM的访问时间也不过是CPU时钟周期的三到四倍,这个差距,也完全可以通过继续细化切分流水级来解决。因此从速度上来说,SRAM作为与CPU直接连接的存储器是合适的。但是我们能不能直接把它作为主存呢?那我们就得来看看价格是否能够接受了。
我们注意到在2010年,同样容量的SRAM,它的价格是DRAM的一千倍。如果说我们现在花一千块钱就可以买到一个非常好的内存条,那你是不是愿意花十万块钱买一个相同容量的SRAM作为内存呢?所以,即使仅从价格因素来考虑,SRAM也无法取代DRAM用来作为内存,而是只能用一个小容量的SRAM作为高速缓存,保存最常用的程序和数据,以达到性能和价格的平衡。
那是什么时候开始用SRAM作为cache加到CPU和主存之间的呢?其实从这张表上我们也能够看出来。在80年的时候,DRAM还是比CPU的速度要快的。所以,这个时候没有使用高速缓存的需求,而到了90年,DRAM的速度已经比CPU慢了。所以,在我们用作例子的这些英特尔系列的CPU中,正是在1980年到1990年这个过程中,逐渐产生了高速缓存的需求。
那在这个时期,我们细致地来看。
早期的8088CPU访存实际上需要840纳秒,而DRAM的延迟是250纳秒,那当然就不需要cache。286的访存周期大约是200纳秒,DRAM的延迟220纳秒,也基本相当,这时候还是不需要cache。而386的访存周期大约是80纳秒,DRAM的延迟虽然有所进步,但还是需要190纳秒,这时候已经明显慢于CPU了。但是386CPU芯片内部并没有设计cache这个部件,后来也发现这对性能有很大的影响。所以,当时是采用在芯片外再增加一块SRAM芯片作为cache来解决这个问题。那么到了486的时候,就已经把cache集成到了CPU芯片的内部,从而缓解CPU和DRAM主存之间的性能差距。
因此,现代的计算机当中都采用了这样层次化的存储结构。在这个层次结构中,越往上的部件,容量越小,但速度更快,而单位字节的成本更高;越靠下的部件,容量更大,但速度更慢,而单位字节的成本更低。
现在,我们已经了解了计算机对存储器的基本需求,也知道了存储器的基本特性和大致的分类。那我们就要对其中的细节进行深入的探索,以及建立完整的计算机存储体系。