Cache是我们经常关心的话题,K6-Ⅲ的推出引出了一种全新的缓存结构即Tri-level Cache设计思想。那么对于微机系统而言,Cache到底有什么作用?它的工作原理又是如何的呢?
一、使用Cache的必要性
所谓Cache即高速缓冲存储器,它位于CPU与主存即DRAM(Dynamic RAM 动态存储器)之间,是通常由SRAM(Static RAM 静态存储器)构成的规模较小但存取速度很快的存储器。
目前计算机主要使用的内存为DRAM,它具有价格低、容量大等特点,但由于使用电容存储信息,存取速度难以提高,而CPU每执行一条指令都要访问一次或多次主存,DRAM的读写速度远低于CPU速度,因此为了实现速度上的匹配,只能在CPU指令周期中插入wait状态,高速CPU处于等待状态将大大降低系统的执行效率。
SRAM由于其采用了与CPU相同的制作工艺,因此与DRAM相比,它的存取速度快,但体积大、功耗大,价格很高,不可能也不必要将所有的内存都采用SRAM。
因此为了解决速度与成本的矛盾就产生了一种分级处理的方法,即在主存和 CPU之间加装一个容量相对较小的SRAM作为高速缓冲存储器。
当采用Cache后,在Cache中保存着主存中部分内容的副本(称为存储器映象), CPU在读写数据时,首先访问Cache(由于Cache的速度与CPU相当,所以CPU可以在零等待状态下完成指令的执行),只有当Cache中无 CPU所需的数据时(这称之"未命中",否则称为"命中"),CPU才去访问主存。而目前大容量Cache能使CPU访问Cache命中率高达90%- 98%,从而大大提高了CPU访问数据的速度,提高了系统的性能。
二、使用Cache的可行性
对大量的典型程序的运行情况分析结果表明,在一个较短的时间内,由程序产生的地址往往集中在存储器逻辑地址空间的很小范围内。在多数情况下,指令是顺序执行的,因此指令地址的分布就是连续的,再加上循环程序段和子程序段要重复执行多次,因此对这些地址的访问就自然具有时间上集中分布的趋向。数据的这种集中倾向不如指令明显,但对数组的访问以及工作单元的选择都可以使存储器地址相对集中。这种对局部范围的存储器地址的频繁访问,而对此范围以外的地址则访问甚少的现象称为程序访问的局部性。根据程序的局部性原理,在主存和CPU之间设置Cache,把正在执行的指令地址附近的一部分指令或数据从主存装入 Cache中,供CPU在一段时间内使用,是完全可行的。
三、Cache的基本工作原理
传统的Socket架构下通常采用两级缓冲结构,即在CPU中集成了一级缓存(L1 Cache),在主板上装二级缓存(L2 Cache);而SlotⅠ架构下的L2 Cache则与CPU做在同一块电路板上,以内核速度或者内核速度的一半运行,速度比Socket下的以系统外频运行的L2 Cache更快,能够更大限度发挥高主频的优势,当然对Cache工艺要求也越高。CPU首先在L1 Cache中查找数据,如找不到,则在L2Cache中寻找;若数据在L2 Cache中,控制器在传输数据的同时,修改L1 Cache;若数据既不在L1 Cache中,又不在L2 Cache中,Cache控制器则从主存中获取数据,将数据提供给CPU的同时修改两级Cache。K6-Ⅲ则比较特殊,64KB L1 Cache,256KB Full Core Speed L2 Cache,原先主板上的缓存实际上就成了L3 Cache。根据有关测试表明:当512K-2MB的三级缓存发挥作用时,系统性能还可以有2%~10%的提高;Tri-level成为PC系统出现以来提出的解决高速CPU与低速内存之间瓶颈最为细致复杂的方案。而且,今后Cache的发展方向也是大容量、超高速。
在主存-Cache存储体系中,所有的指令和数据都存在主存中,Cache只是存放主存中的一部分程序块和数据块的副本,只是一种以块为单位的存储方式。Cache和主存被分为块,每块由多个字节组成。由上述的程序局部性原理可知,Cache中的程序块和数据块会使CPU要访问的内容大多数情况下已经在Cache中,CPU的读写操作主要在CPU和Cache之间进行。CPU访问存储器时,送出访问单元的地址,由地址总线传送到Cache控制器中的主存地址寄存器MA,主存—Cache地址转换机构从MA获取地址并判断该单元内容是否已在Cache中存有副本,如果副本已存在Cache中,即命中。当命中时,立即把访问地址变换成它在Cache中的地址,然后访问Cache。
如果CPU要访问的内容不在Cache中,即不命中,则CPU转去直接访问主存,并将包含此存储单元的整个数据块(包括该块数据的地址信息)传到 Cache中,使得以后的若干次对内存的访问可转化为对Cache的访问。若Cache存储器已满,则需在替换控制部件的控制下,根据某种替换算法/策略,用此块信息替换掉Cache中的原来的某块信息。
所以,要想提高系统效率,必须提高Cache命中率,而Cache命中率的提高则取决于Cache的映象方式和Cache刷新算法等一系列因素;同时 Cache中内容应与主存中的部分保持一致,也就是说,如果主存中的内容在调入Cache之后发生了变化,那么它在Cache中的映象也应该随即改变,反之,当CPU修改了Cache中的内容后,主存中的相应内容也应作修改。
从上面的简单介绍中,我们知道了Cache也是一类存储器,它是为了解决CPU与主存之间速度匹配问题而设置的,且不能由用户直接寻址访问。下篇将就Cache映象问题、刷新问题和保持数据一致性问题作简要论述。
四、地址映像
所谓映象问题是指如何确定Cache中的内容是主存中的哪一部分的拷贝,即必须应用某种函数把主存地址映象到Cache中定位,也称地址映象。当信息按这种方式装入Cache中后,执行程序时,应将主存地址变换为Cache地址,这个变换过程叫作地址变换。地址映象方式通常采用直接映象、全相联映象、 组相联映象三种。
1.直接映象
每个主存地址映像到Cache中的一个指定地址的方式,称为直接映象方式。在直接映象方式下,主存中存储单元的数据只可调入Cache中的一个位置,如果主存中另一个存储单元的数据也要调入该位置则将发生冲突。地址映像的方法一般是将主存空间按Cache的尺寸分区,每区内相同的块号映像到Cache 中相同的块位置。一般地,Cache被分为2N块,主存被分为同样大小的2M块,主存与Cache中块的对应关系可用如下映像函数表示:j = i mod 2N。式中,j是Cache中的块号,i是主存中的块号。
直接映象是一种最简单的地址映像方式,它的地址变换速度快,而且不涉及其他两种映像方式中的替换策略问题。但是这种方式的块冲突概率较高,当称序往返访问两个相互冲突的块中的数据时,Cache的命中率将急剧下降,因为这时即使Cache中有其他空闲块,也因为固定的地址映像关系而无法应用。
2.全相联映象
主存中的每一个字块可映像到Cache任何一个字块位置上,这种方式称为全相联映像。这种方式只有当Cache中的块全部装满后才会出现块冲突,所以块冲突的概率低,可达到很高的Cache命中率;但实现很复杂。当访问一个块中的数据时,块地址要与Cache块表中的所有地址标记进行比较已确定是否命中。在数据块调入时存在着一个比较复杂的替换问题,即决定将数据块调入Cache中什么位置,将Cache中那一块数据调出主存。为了达到较高的速度,全部比较和替换都要用硬件实现。
3.组相联映象
组相联映象方式是直接映象和全相联映象的一种折衷方案。这种方法将存储空间分为若干组,各组之间是直接映像,而组内各块之间则是全相联映像。它是上述两种映像方式的一般形式,如果组的大小为1,即Cache空间分为2N组,就变为直接映像;如果组的大小为Cache整个的尺寸,就变为了全相联映像。组相联方式在判断块命中及替换算法上都要比全相联方式简单,块冲突的概率比直接映像的低,其命中率也介于直接映像和全相联映像方式之间。
五、替换策略和一致性问题的处理方法
Cache和存储器一样具有两种基本操作,即读操作和写操作。
当CPU发出读操作命令时,根据它产生的主存地址分为两种情形:
一种是需要的数据已在Cache中,那么只需直接访问Cache,从对应单元中读取信息到数据总线;
另一种是需要的数据尚未装入Cache,CPU需从主存中读取信息的同时,Cache替换部件把该地址所在的那块存储内容从主存拷贝到 Cache中;若Cache中相应位置已被字块占满,就必须去掉旧的字块。常见的替换策略有两种:
1.先进先出策略(FIFO)
FIFO(First In First Out)策略总是把最先调入的Cache字块替换出去,它不需要随时记录各个字块的使用情况,较容易实现;缺点是经常使用的块,如一个包含循环程序的块也可能由于它是最早的块而被替换掉。
2.最近最少使用策略(LRU)
LRU(Least Recently Used)策略是把当前近期Cache中使用次数最少的那块信息块替换出去,这种替换算法需要随时记录Cache中字块的使用情况。LRU的平均命中率比 FIFO高,在组相联映像方式中,当分组容量加大时,LRU的命中率也会提高。
当CPU发出写操作命令时,也要根据它产生的主存地址分为两种情形:一种是不命中时,只向主存写入信息,不必同时把这个地址单元所在的整块内容调入Cache中;另一种是命中时,这时会遇到如何保持Cache与主存的一致性问题,通常有三种处理方式:
1.直写式(write through)
即CPU在向Cache写入数据的同时,也把数据写入主存以保证Cache和主存中相应单元数据的一致性,其特点是简单可靠,但由于CPU每次更新时都要对主存写入,速度必然受影响。
2.缓写式(post write)
即CPU在更新Cache时不直接更新主存中的数据,而是把更新的数据送入一个缓存器暂存,在适当的时候再把缓存器中的内容写入主存。在这种方式下,CPU不必等待主存写入而造成的时延,在一定程度上提高了速度,但由于缓存器只有有限的容量,只能锁存一次写入的数据,如果是连续写入,CPU仍需要等待。
3.回写式(write back)
即CPU只向Cache写入,并用标记加以注明,直到Cache中被写过的块要被进入的信息块取代时,才一次写入主存。这种方式考虑到写入的往往是中间结果,每次写入主存速度慢而且不必要。其特点是速度快,避免了不必要的冗余写操作,但结构上较复杂。
此外,还有一种设置不可Cache区(Non-cacheable Block)的方式,即在主存中开辟一块区域,该区域中的数据不受Cache控制器的管理,不能调入Cache,CPU只能直接读写该区域的内容。由于该区域不与Cache发生关系,也就不存在数据不一致性问题。目前微机系统的BIOS设置程序大多允许用户设置不可Cache区的首地址和大小。