存储器层次结构设计汇总.docx
- 文档编号:12542656
- 上传时间:2023-04-20
- 格式:DOCX
- 页数:75
- 大小:1,020.66KB
存储器层次结构设计汇总.docx
《存储器层次结构设计汇总.docx》由会员分享,可在线阅读,更多相关《存储器层次结构设计汇总.docx(75页珍藏版)》请在冰豆网上搜索。
存储器层次结构设计汇总
第五章存储器层次结构设计
在理想情况下,我们希望存储容量无限大,这样任何一个特定的…字都可以立刻获取…我们…不得不认识到构建存储器层次结构的可能性,它们中的每一层都比其上一层具有更大的容量和更慢的访问速度。
A.W.Burks,H.H.Goldstine,和J.vonNeumann
电子计算设备逻辑设计预备讨论会(1946)
5.1简介
计算机的先驱们正确地预见到了编程者希望拥有无限大容量的快速存储器。
一个解决这个问题较经济的方法就是采用存储器层次结构,其依据是程序访问的局部性原理和内存技术的性能价格比原则。
在第一章中所阐述的局部性原理认为大部分程序并不是均衡的访问所有的代码和数据(参见1.6节)。
这个原理以及越小硬件、其速度越快这个指导思想,产生了基于不同速度和容量的存储器层次结构。
图5.1显示了一个多级存储器层次结构,其中包括了典型的各层次容量大小和存取速度值。
图5.1一个通用于嵌入式系统、桌面处理器、服务器的典型多级存储器层次结构。
距离CPU越远的层次,存储容量越大,存取速度越慢。
注意,不同层次的存取时间的变化系数为10:
从微微秒到毫秒之间变化;而容量大小的变化系数为1000:
从几字节到几千兆字节之间变化。
图5.3将给出桌面处理器、小型服务器的更多参数指标。
由于快速存储器较为昂贵,因此将存储器层次结构可以组织成几个不同层次——每一层都比它更低一层具有更小的容量,更快的速度、当然每字节的价格也更高。
这种组织结构的目标是提供一个存储器系统,使之能够具有几乎相当于最便宜层次的存储器的价格,但是访问速度却与最快层次的存储器接近。
层次结构中的各层之间通常是子集关系,某一层中的所有数据也总能在其低一层中找到,而低一层中的所有数据也能在更低一层中找到,如此直到层次结构的最底层。
在层次结构中,每一层都要从一个较大的存储器空间中把地址映射到一个较小、但是更快的、位于上一层的存储器中。
作为地址映射的一部分,存储器层次结构具有地址检查的功能,因此,用于监察地址的保护机制也是存储器层次结构的一部分。
随着处理器性能增长,存储器层次结构的重要性不断增加。
例如,在1980年,微处理器一般是不带Cache的,但是到了2001年,处理器芯片内部通常带有两级Cache。
正如在第一章中提到的:
1986年以前,微处理器的性能改进是平均每年提高35%;从1987年以后,微处理器的性能改进则达到了平均每年提高55%。
图5.2描绘了CPU性能伴随着主存访问性能提高的预测增长情况。
显然,计算机体系结构设计者必须尽力去缩小处理器—主存之间的性能差距。
图5.2以1980年性能为基准,存储器和CPU的性能差距随时间的变化曲线。
存储器的基准是1980年的64-KBDRAM,三年更新换代、在延迟上每年都有7%的性能增长(参见图5.30)。
CPU曲线表示:
1986年以前CPU性能每年增长1.35倍,而此后每年增长1.55倍。
图中纵轴是用对数坐标来表示CPU-DRAM性能差距。
本章将描述为减少处理器-存储器的性能差距而提出的一些改进方法。
为便于理解这些抽象的改进方法,在本章中,我们以四级存储器层次结构、采用Alpha21264微处理器的计算机系统作为应用实例。
在本章的最后,我们利用SPEC95benchmark程序评价了这些层次结构对系统性能的影响。
21264微处理器是专为桌面处理器和服务器设计的。
即使是这两类相关联的计算机系统,它们在存储器层次方面也有着不同的侧重点。
桌面处理器在操作系统的控制下,一次只为单个用户运行一个应用程序;而服务器则有可能同时为成百上千个用户执行大量的应用程序。
服务器的这些特征导致了更多的上下文切换,显著增加了强制性缺失率。
因此,桌面处理器主要关注于存储层次结构带来的平均延迟问题,而服务器除此之外,还需要考虑存储带宽问题。
尽管在桌面处理器中阻止程序间数据混淆的保护机制很重要,但是服务器同时还必须兼顾防止一个用户存取其他用户的数据,因而更突出保护升级的重要性。
服务器的发展趋向于大型化,拥有更大内存和更多磁盘存储,运行更多更大的应用程序。
在2001年,服务器通常都是拥有成千上百个磁盘的多处理器配置,要求存储层次结构拥有很大带宽。
嵌入式计算机与桌面处理器、服务器计算机的存储层次结构有很大不同。
首先,嵌入式计算机一般用于实时处理,程序员必须考虑到最坏情况时的性能。
这时,尽管采用Cache结构能够提高平均性能,但是会降低最坏情况时的性能,因此是否采用Cache结构还存在争议。
对此,我们将在本章中后续章节中讨论一些改进技术。
其次,嵌入式应用程序常常关注于电源和电池寿命。
节省功耗的最好办法是减少硬件,因此,嵌入式计算机不能象大多数桌面处理器和服务器一样,用扩展硬件优化的方法来获取更好的存储层次性能。
第三,典型的嵌入式应用程序采用非常简单的操作系统,只运行一个应用程序,因而可以不考虑存储层次保护机制。
最后,嵌入式处理器的主存可能很小(不到1MB),并且常常不需要磁盘存储。
本章我们以桌面处理器为例,对存储器层次结构的基本原理进行讨论,指出其与服务器、嵌入式计算机在存储层次结构上的不同。
除了Alpha21264之外,本章最后将会给出SonyPlaystation2和SunFire6800服务器中的存储器层次结构。
5.2Cache回顾
Cache:
隐藏或存储东西的安全地点
韦伯思特美语新世界词典,第二版(1976)
本节我们先来回顾一下Cache基本概念,涉及到的内容有以下36项:
高速缓存(Cache)全相联写分配
虚拟存储器重写位一体Cache
存储器停顿周期块内偏移每条指令缺失次数
直接映射写回法块
有效位数据Cache局部性
块地址命中时间地址跟踪
写通过Cache缺失组
指令Cache页缺失随机替换
平均存储器存取时间缺失率索引域
Cache命中n-路组相联非写分配(no-writeallocate)
页最近最少使用写缓冲
缺失代价标志域写停顿(writestall)
知道上面这些术语意义的读者,可以跳到“一个例子:
Alpha21264数据Cache”部分,甚至直接跳到5.3节“Cache性能”。
(如果觉得本节的回顾太快的话,可以参考第7章“计算机结构与设计”,这是针对经验较少的读者编写的。
)
存储器层次结构中最重要的两层是Cache和虚拟存储器。
Cache通常是存储器层次结构中第一层的名字,是距离CPU最近的存储层次。
既然局部性原理应用到了许多方面,而且利用其优点来提高性能是非常普遍的,所以术语Cache如今被应用到了任何通过缓冲区来重复利用经常发生事件上;这些例子包括文件Cache,命名Cache等等。
当CPU在Cache中找到要访问的数据项时,被称为一次Cache命中;当CPU找不到所需要的数据项时,称为Cache缺失。
包含所需要的字的一固定大小的数据集合被称为“块”,它从内存中获取、并放置到Cache中。
由时间局部性原理可知,我们在不久的将来可能会再次用到这个字,所以将它放到CPU能较快访问到的Cache中是很值得的。
根据空间局部性,块内的其他数据也可能在不久的将来被访问。
发生Cache缺失时,数据存取时间取决于存储器的延迟和带宽。
延迟决定了读取该块第一个字的时间,而带宽决定了读取该块中其他部分所需要的时间。
Cache缺失通常由硬件处理,导致顺序执行处理器暂停或停止处理,直到所需数据可用为止。
类似地,一个程序需要的所有数据并不是都驻留在内存中。
如果系统中包含虚拟存储器,那么一些数据可以存放在磁盘中。
地址空间通常分为一些固定大小的块,称为“页”。
任何时候,每个页保存在主存储器或者磁盘中。
当CPU要访问的数据项既不在Cache、又不在主存储器中时,则发生“页缺失”,需要从磁盘中取出该页并放到主存储器中。
页缺失花费的时间比较长,通常由软件来处理,这时,CPU并不停止工作,而是切换到其他任务继续执行。
Cache与主存储器的关系和主存储器与磁盘的关系相同。
图5.3显示了从高端桌面处理器到低端服务器各类计算机系统中,存储器层次结构中每一级的容量大小和存取时间范围。
图5.3大型工作站和小型服务器中典型存储层次结构:
距离CPU越远,存储速度越慢、容量越大。
嵌入式计算机可以没有磁盘存储,并且具有小得多的内存和Cache。
存取时间随着层次结构从高层往低层依次增加,这种结构对不敏感数据传输的管理是合理的。
“实现技术”一栏给出了实现这些功能的典型技术。
存取时间给出的是在2001年典型的纳秒级数据,这些时间还会进一步减少。
存储层次各级间的带宽以兆字节/秒为单位。
磁盘存储器的带宽包括了存储介质和缓冲区接口。
Cache性能回顾
根据局部性原理和小存储器具有较快存取速度原理可知,存储器层次结构能从实质上改进计算机性能。
我们可以扩展第一章中的CPU执行时间公式来评估Cache的性能改进程度。
我们将CPU暂停工作、等待一次存储器存取的周期数称为存储器停顿周期数,性能可以表示为CPU时钟周期数与存储器停顿周期数的和,再与时钟周期时间的乘积:
等式中假定CPU时钟周期数包含了处理Cache命中和Cache缺失时CPU停止的时间。
5.3节将会校验这个简化的假设。
存储器停顿周期数由缺失次数和每一次的缺失代价所决定:
最后一种表示形式的优点是每一个因子都能很容易得到。
我们已经知道如何计算执行指令数(对于预测型CPU,我们只计算指令计数器IC完成的指令),测定每条指令的存储器访问次数可用同样的方式;每条指令都需要一次取指令,并且我们很容易判断出该指令是否会存取数据。
注意,我们把缺失代价作为平均数参与计算,但在后面的讨论中我们将它看作是一常数。
当发生Cache缺失时,Cache下一层次的存储器由于上一层存储器需求和存储器刷新而变得很忙碌。
并且,处理器、总线和存储器间接口的时钟周期数也是不同的。
因此,我们把缺失代价简化为一个数值。
缺失率是Cache访问中产生缺失所占访问总数的百分率(也就是产生缺失的Cache访问次数除以访问总次数)。
缺失率可以用Cache仿真器来测量:
仿真器对要进行访问的指令和数据进行地址跟踪,模拟Cache行为来判断是命中还是缺失,并给出命中和缺失的总数。
一些微处理器提供了硬件来计算缺失数和存储器引用次数,这使得缺失率的计算变得更为简单和快速。
读、写Cache操作的缺失率和缺失代价往往是不同的,因此上面的公式只是一近似公式。
存储器停顿周期数可以由每条指令的访存次数、读和写的缺失代价(以时钟周期计)和缺失率来定义:
可以将读、写合并,计算出它们的平均缺失率和缺失代价,从而将上述公式简化为:
缺失率是Cache设计最重要的因素之一,然而,在后续的章节中,我们将会看到它并不是唯一的因素。
例假定有一台计算机,当所有访存操作都能在Cache命中时,每条指令的时钟数(CPI)为1.0。
对数据存取只包含读入和存储,这些指令占全部指令的50%。
缺失代价为25个时钟周期,缺失率为2%,问当所有指令都在Cache中命中时,计算机性能提高多少?
解
首先计算Cache始终命中时的机器性能:
再看现实中有Cache的操作情况,首先计算存储器停顿周期数:
上式中,(1+0.5)表示每条指令包括一条指令存取和0.5条数据存取。
因此,总性能表示如下:
性能比就是两个执行时间的比值:
由此可知,不发生Cache缺失时,计算机性能提高1.75。
一些设计者喜欢用平均每条指令缺失次数、而不是平均每次存储器存取缺失数来度量缺失率:
当知道每条指令平均访存次数时,可以将缺失率转换为每条指令缺失次数,因此后一个公式更为有用。
例如,我们可以将上例中的访存缺失率转换成每条指令缺失次数:
通常情况下,为了让每条指令的缺失次数表示为整数,我们一般采用每千条指令的缺失次数来计算。
这样,上面的答案也可表示成每千条指令发生缺失30次。
这种度量方法的优点是它独立于硬件实现。
例如,21264指令预取单元取到的指令条数为实际用到的2倍,如果采用每次存储器存取而不是每条指令的缺失数来度量缺失率,就会人为的降低缺失率。
它的缺点是平均每条指令缺失数与处理器体系结构相关:
例如,平均每条指令存储器存取次数,对于80X86和MIPS来说可能是完全不同的。
总而言之,尽管与RISC类似的系统结构允许我们参照其他参数,在单一计算机家族情况下,系统结构设计师一般采用每条指令缺失次数。
例为表明两个缺失率等式的相等关系,我们重新看一下上面的例子。
这次假定缺失率为每千条指令缺失30次,以指令数计算的存储器停顿周期是多少?
解
计算存储器停顿周期:
我们得到的答案与上面相同。
存储器层次结构的四个问题
通过回答四个基本问题,我们继续对存储器层次结构第一层次——Cache进行描述。
Q1:
块的放置:
在较高层中,一个块能被放置在哪里?
Q2:
块的标识:
如果一个块在较高层中,如何找到它?
Q3:
块的替换:
如果没有命中,哪个块应该被替换?
Q4:
写时策略:
写操作时会发生什么?
对这些问题的回答,能帮助我们理解在存储器层次结构中各层次之间的均衡方式;因此,我们对每个例子都提出这四个问题。
Q1:
一个块可以被放置到Cache的哪里?
图5.4给出了根据块放置策略来划分的三种Cache组织形式:
⏹如果每个块在Cache中只能出现在唯一位置上,那么这种映射就叫做直接映射,映射方法通常是:
(块地址)MOD(Cache中的块数)
⏹如果一个块可以放到Cache中的任何一个地方,那么这种映射就叫做全相联映射。
⏹如果一个块可以放到Cache中一个受限的组里,那么这种映射就被叫做组相联映射。
一个组(set)是Cache中的一组块。
一个块首先被映射到一个组中,然后它可以被搁置到组中的任何一块中。
组通常利用位选择方式确定,即:
(块地址)MOD(Cache中的组数)
如果一个组里有n块,那么这种映射方法就被叫做n-路组相联。
图5.4例中Cache分成8个块结构,主存有32个块。
Cache的三种策略从左到右如上所示。
假定Cache开始时是空的,而要分配的块地址在主存中为12。
在全相联方式中,主存块12可以进入到Cache的8个块中的任何一个。
在直接映射方式中,主存块12只能放到块4处(12模8)。
组相联方式具有上述两种方式的某些特征,允许块被放置到组0(12模4)中的任何一个位置上。
因为每组两块,所以这意味着块12可以被放置到Cache的块0中或块1中。
真正的Cache包括几百个块结构,而真正的主存则包含了成百万的块。
组相联方式有4个组、每组两个块,因而叫做2-路组相联。
直接映射和全相联实际上是组相联的两种特殊情况:
直接映射仅仅是一个简单的1路组相联,而一个有m块的全相联Cache可以被称作m-路组相联;也就是说,直接映射可以看成是有m组的组相联映射,而全相联是只有1组的组相联映射。
今天的大多数处理器的Cache采用直接映射,两路组相联映射,或是四路组相联映射方式。
Q2:
如果某一块在Cache中,如何找到它?
Cache中的每一块结构都有一个地址标志,从而给出块地址。
当查找希望获得的信息时,是通过对每一个Cache块标志进行检查,看它是否与来自CPU的块地址相匹配来实现的。
考虑到速度的重要性,所有可能的标志都要被并行检查。
必须要有一种方法来确定一个块中是否包含有效信息。
最普通的方法是在标志中加上一个有效位,来表明该条目(entry)是否包含有效地址。
如果这个位没有设置,则该地址不能进行匹配。
在继续下一个问题之前,我们先来看一下CPU地址同Cache地址间的关系。
图5.5给出了Cache地址的划分情况:
第一个划分是在块地址和块内偏移之间作出的;块地址可以进一步细分成标志域和索引域。
块内地址偏移用来从块中选出需要的数据,索引域用来选择组,通过比较标志域来判断是否发生命中。
判断是否命中时,没有必要对除标志域以外的更多地址位进行比较,原因如下:
⏹块内偏移是没有必要比较的,这是因为Cache命中与否的单位是整个块,因此所有块内的地址偏移将会是匹配的。
⏹由于索引域是用来选择被检查的组,所以对索引域的比较是多余的。
例如,一个地址存储在组0中,则在索引域中必然包含0,否则不可能被存储在组0中;组1一定有索引值1;依次类推。
这种优化通过减少Cache标志域长度来节省了硬件开销和功耗。
图5.5组相联或直接映射中地址的三个部分。
标志域用来检查组中的所有块,而索引域用来选择组。
块内地址偏移是块内期望数据的地址。
全相联映射没有索引域。
如果Cache的大小一定,增加相联度将增加每一个组中的块数,因而减少了索引域的宽度,但是增加了标志域的宽度。
也就是说,图5.5中的标志—索引界限将根据增加的相联度向右移动,最后如果变成全相联的话,将不存在索引域。
Q3:
如果没有命中,哪个块应该被替换?
当缺失发生时,Cache控制器必须选择Cache中的一个块,并用期望获得的数据块来替换它。
使用直接映射替换方法的优点是硬件决策简单——事实上,它根本不需要任何选择:
只检查一个块结构是否命中,当不命中时,也只有这个块可以用于替换。
如果是全相联或是组相联,则发生缺失时就要从多块中作出适当的选择。
有三种基本的块替换策略:
⏹随机替换策略——为了均匀地分配,候选块将被随机选择。
一些系统产生伪随机数块号,以获得可重复的行为,当调试硬件时,这种方式尤其有用的。
⏹最近最少使用(LRU)替换策略——为了减少替换那些可能不久就要用到信息的机率,需要记录块的访问次数。
利用历史信息来预测未来使用情况,被替换的块将是最长时间内没有被访问的Cache块。
LRU使用了一个局部性原理的推论:
如果一个最近被使用的块很可能会被再次访问,那么最佳替换块将是最近最少使用的块。
⏹先进先出(FIFO)替换策略——由于计算LRU比较复杂,该替换策略将最早进入Cache的块作为替换块。
随机替换的优点是硬件简单。
当跟踪的块数增加时,LRU硬件也随之变得更为复杂,而且通常仅仅是近似的。
图5.6给出了LRU、随机和先进先出三种替换策略在缺失率上的差别。
图5.6最近最少使用、随机和先进先出三种替换策略,在不同Cache大小和相联度情况下,每千条指令缺失率比较。
这些数据是在Alpha系统结构计算机中,通过运行十个SPEC2000基准测试程序得到的,Cache块大小为64字节。
在十个基准测试程序中,5个来自于SPECint2000(gap,gcc,gzip,mcf,perl),另外5个来自于SPECfp2000(applu,art,equake,lucas,swim)。
这里,对于大容量Cache,LRU和随机替换几乎没有差别;对于小容量Cache,LRU替换策略最优,先进先出(FIFO)算法要比随机算法性能略好一些。
在本章后面的大多数图表中,我们都会以这个计算机系统和这些基准测试程序为例来说明。
Q4:
写操作时会发生什么?
读操作决定着处理器Cache的访问次数。
所有的指令都是通过读操作来获得的,而且大部分指令并不进行存储器写操作。
第二章中图2.32给出了一个包含了10%存储指令和37%加载指令的MIPS的混合程序所产生的写操作,占全部存储器通讯量的10%/(100%+37%+10%),即大约7%;而占数据Cache的通讯量的10%/(37%+10%),即大约21%。
这样,加快经常性事件速度就意味着要优化读Cache的时间,尤其是对传统处理器,它们需要等待读操作完成、但是却不必等待写操作完成就可以进行其他操作。
然而,Amdahl定律(1.6节)提醒我们高性能的设计不能忽视写速度对系统性能的影响。
幸运的是,读操作也是很容易提高速度的。
块可以在标志位读和比较的同时被读出,所以读块操作是在获得块地址的同时就开始了。
如果读命中,块中所需信息立刻被传送到CPU。
如果没有命中,这样做虽然没有得到好处——但是在桌面机和服务器中,这也没有什么坏处,只需把读到的信息丢弃即可。
而在嵌入式系统中,降低功耗的前提要求避免进行无用工作,因而设计者通常是把读取数据和地址检查分开,使得发生缺失时数据不被读取。
对于写操作来说,这样的优化却不适用。
只有标志位有效而且地址命中时,块才能被修改。
因为标志位检查不能与写数据并行进行,写操作通常要比读操作需要更长的时间。
另一个复杂情况是处理器必须给出要写数据的大小,通常在1到8字节之间;只有块中的这一部分可以被改变。
与写操作不同,读操作可以读取比所需字节数更多的信息;同样,嵌入式系统设计者要权衡少读信息所带来的功耗收益。
写策略通常可以用于区分Cache设计。
通常有两种基本策略用来写Cache:
●写通过(writethrough)——信息被同时写到了Cache块和更低一层存储器的块中。
●写回法(writeback)——信息只被写入Cache块。
只有Cache中该块被替换出去时,信息才会被写回到主存中。
为了减少替换时块的写回频率,通常需要使用一个叫做重写位(dirtybit)的特征信息位。
这个特征位表明一个块是脏的(在Cache中被修改)还是干净的(在Cache中没有被修改)。
如果它是干净的,在发生缺失需替换该块时,因为下层存储器同Cache包含有相同的信息,该块不必写回。
写回法和写通过法各有优点。
在写回法中,写操作和Cache存储器的速度是一致的,而且对同一个块中的多次写入仅仅需要对下层存储器一次写操作。
因此,写回法需要较小的存储带宽,这种方法在多处理器的服务器系统中更具有吸引力。
相对于写通过法,写回法对其他存储器层次和存储总线的使用较少,节省了功耗,因而很受嵌入式应用程序的青睐。
写通过法比写回法更易实现。
在写通过法中,当读操作发生缺失时,由于Cache始终是干净的,因此不必对较低层存储器进行写操作。
写通过法还可以保证低层存储器有当前最新数据的副本,这简化了数据一致性问题。
数据一致性(见5.12节)对于多处理器系统和I/O系统是很重要的,我们将会在第6章和第7章中进一步讨论。
正如我们将要看到的,I/O系统和多处理器系统是反复无常的:
它们希望处理器Cache利用写回法来减少存取通讯量,同时也希望利用写通过法来保证存储器层次结构中Cache和低层存储器数据的一致性。
在写通过法中,如果CPU的操作必须等待写操作完成才能进行时,这种CPU被称做是写停顿(writestall)的。
通常用来减少写停顿的优化策略是写缓存技术,它允许处理器把数据写入到缓冲区之后立刻继续工作,因此使处理器执行时间和存储器更新时间重叠。
我们将会看到,即使是利用写缓存技术,写停顿仍然可能发生。
因为在写操作时并不需要数据,因而在写缺失时有两种通常策略:
⏹写分配(writeallocate)——在发生写缺失时,主存的块被读到Cache中,然后执行前面写命中时的操作。
与读缺失类似。
⏹非写分配(no-writeallocate)——仅修改低层存储器中的该块,而不将该块取到Cache中,因而写缺失不影响Cache内容。
在非写分配中,直到程序要读一个块时,该块才被存取到Cache中;而在写分配中,只要被写的块就会保存在Cache中。
让我们看一个例子。
例有一全相联映射的Cache,采用写回策略,刚开始时Cache为空。
有下面5个存储器操作(方括号中为地址):
WriteMem[100];
WriteMem[100];
ReadMem[200];
WriteMem[200];
Wr
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 存储器 层次 结构设计 汇总