在计算机存储体系中,cpu与主存乃至外存的速度相差过大,如果每次都直接从中取出数据,cpu需要耗费大量时间在读写上,为了提高利用率,分级存储系统就是为了缓解这一问题。
但cache作为靠近cpu的一级存储器,并不能将内存做的过大。cache一般由SRAM制成,每个单位都需要6个MOS管,这就意味着cache的集成度低,而且成本更高。
在计算机中存在着两个局部性理论:空间局部性理论指出,最近未来会用到的数据和指令,很可能和当前指令或数据存在接近的空间位置。时间局部性理论指出,最近未来会用到的数据和指令,很可能是现在正在使用的信息。基于局部性原理,我们可以将当前访问地址的附近内容装入cache,方便cpu取用。
在使用cache时,将主存和cache均分为相等大小的小内存块。以块为单位交换数据。 例:主存4MB,相当于22位地址可达。如果以1KB为单位分配可以分为4096块。这22位地址就分为了12位块号和10位块内地址。 在执行将主存块内容搬入对应cache块时,由于主存块数量肯定多于cache块数量,有三种常见的映射方式决定它们之间要如何匹配:
1)直接映射 直接对二者进行映射 每个cache可存放 目标主存号%cache总块数 的主存块 假如有6个主存块,3个cache块,那么1号cache块可存放1、4号主存块,2-->2、5,3-->3、6
2)全相联映射 任意cache块可存放任意主存块
3)组相联映射 先将cache分组, 每组内任意cache都可存放 目标主存块号%cache组数 的主存块。也就是说将直接映射的单位变成了一组cache块。
为了拷贝数据,需要主存到cache之间的映射关系,这些映射关系被存放在映射关系表中。
------------
在实际使用中,cache每块前可以加一个标记,用来记录自己存储主存块号;除了块号,还要添加一个有效位,用于标记是否用过该块。
-------------
在拥有了cache后,CPU访问数据的操作是这样的:首先在cache中检查是否有对应块,如果有则直接取用,此时称为命中。如果没有,还需要去访问主存。
cache的容量有限,如果对应的cache已经被使用,但此时又有新内存需要载入,那么就需要使用到cache的替换算法:
1)随机替换 RAND
2)先进先出 FIFO 最先被使用的cache块先被替换
3)近期最少优先,LRU 每个cache块上加入计数器,记录该块已经有多久未被使用,每次替换时替换最久无用块。 在每次调入一个内存数据块时,新cache块计数器置零,而其他cache块计数全部+1.
4)最不经常使用 LFU 同样有计数器,但此时计数器记录的是该块被访问的次数。调入新块时,新块的计数器置零。
-------------
在使用cache时,由于cache本质就是拷贝了一小部分的主存数据,所以CPU在操作时产生了一个问题:如果CPU修改了数据,那么如何保证cache和主存的数据是同步的?
在cache的写策略中,根据是否命中,有四种策略可以使用:
命中时:
1)写回法:CPU命中时,只修改cache的数据,此块被置换出去以后才写回内存;使用这种策略时,每块cache还要增加一个标志位标记此块是否被使用过。
2)全写法:命中时,cache和对应主存的数据都修改;
未命中时:
1)写分配法:先把数据调入cache块,然后修改cache的数据,一般这种方式要配合写回法使用;
2)非写分配法:如果没有命中,直接修改主存的数据,不再调入cache。
一般情况下,cache不止一级,各级cache间使用全写法+非写分配法,cache和主存间使用写回法+写分配法。
-----------------
注:cache等存储器操作不需要CPU的参与,它们对于CPU来说是完全透明的。