Cache的三种映射和局部性
作者:互联网
计算机存储层级结构
上图是计算机的存储的层次结构图,自上而下,运行速度越来越慢,存储容量越来越大
其实CPU在运行时,所需要的操作数大多数是来自寄存器的,速度是很快的,而离CPU越远的,运算速度越慢
就我个人的理解,cache就是我们CPU内部的SRAM,主存是DRAM,也就是我们经常听说的内存条,外存储就是硬盘之类的
我们应该了解,计算机在运行时,操作指令多存放在主存(内存条)中,再结合上图可以发现,主存并不是离寄存器最近的存储器件,那么为了提高计算机的速度,应当将运行指令先从主存中拷贝到cache中,对DRAM和SRAM有过了解的小伙伴应该知道,SRAM运行速度快,但成本高;DRAM运行速度相对慢,但是价格相对便宜,因此cache的容量必定不会与主存的容量大小相同
那么如何保证从主存拷贝到cache中的指令和数据正是我们所需要的呢?
这就涉及到了程序访问的局部性
程序访问的局部性
分析结果表明:
在较短时间间隔内,程序产生的地址/所访问数据往往几种在存储器的一个很小范围内
程序访问局部性可以分为:时间局部性和空间局部性
- 时间局部性:刚被访问过的存储单元很可能不久后又被访问
- 空间局部性:刚被访问过的存储单元临近的单元很可能不就后被访问
这里再来介绍个概念
CPU和cache之间是以字
进行指令/数据的传输
主存和cache之间是以块
进行指令/数据的传输,每个块中又包含多个字(单元)
当CPU要从主存中读取指令/数据的时候,会先查看cache中有没有,如果有直接调用cache中的指令/数据,如果没有则先从主存中拷贝到cache中,在从cache中调用
从两个局部性分别来看
- 时间局部性:对于从主存拷贝到cache中的指令/数据,如果不与映射方式冲突,不会在CPU调用完后就立即擦除(映射方式接下来会介绍),可以理解为,被CPU调用的指令/数据还是保留在cache中,如果下次再次调用这些指令/数据,它们还在cache中,不用从主存取
- 空间局部性:因为从主存中拷贝到cache中的指令/数据是以块为单位的,假如说一个块中有10个数字,刚开始CPU想访问在数字1位置的指令/数据,而cache此时将数字0-9都拷贝进cache中,那么下次CPU想访问在数组5中的指令/数据时,它们也都在cache中
cache与主存的映射
cache与主存可按三种方式进行映射:直接映射、全映射、组映射
直接映射
(直接从网上的视频中摘个题目)
因为主存和cache之间是以块为单位进行传输的,因此cache和主存中每个块的大小要相同
这是直接映射的示意图
从题目中给的计算结果看,cache共分为16个槽(也叫行),主存共分为2048个块
将主存的块根据cache的槽数进行块群的划分
128个块群是由主存的2048个块 / cache的16个槽
得来的,主存中每个块群有16个块
直接映射就是每个块群的第几个块只能映射到cache的第几个槽中
这么说有点抽象,换个说法
0块是0块群的第一个块,那么0块就只能映射到cache的第一个槽(0槽);16块又是1块群中的第一个块,那么16块也只能映射到cache的第一个槽(0槽)
在介绍局部性的时候,我有提过“如果不与映射方式冲突”,试想一下,按照直接映射的方式,CPU第一次访问的是主存的0块,下次访问的是主存的16块呢
接下来介绍地址
从这个图中可以看到,地址分为:主存地址、主存块号、主存标记、cache槽号、块内地址和cache地址
-
块内地址指出来每个块中访问的是第几个单元
-
cache槽号指出存储在第几个槽中
-
cache槽号指出指令/数据存储在cache中第几个槽的第几个单元中
-
主存标记指出访问的是主存中的第几个块群
-
主存块号(主存标记+cache槽号)指出访问的是主存的第几个块
比如我们要对0220CH单元进行访问
0220CH转换成二进制是 0000_0010_0010_0000_1100B
主存标记是前7位 -> 0000_001 (1块群)
cache槽号是主存标记后面的4位 -> 0_001 (1槽)
块内地址是最后的9位 -> 0_0000_1100 (12单元)
主存块号是前11位 -> 0000_0010_001 (17块)
即0220CH单元是主存中1块群1块(17块)中的12单元
直接映射访问方式:
假如CPU想访问主存0块中的12单元,CPU先查看cache的0槽(0块应当映射到0槽中)是否存在0块的内容,如果没有则先将主存0块中的内容拷贝到cache的0槽,在从cache中访问
试想一下,假设我们的cache固定,就是16个槽,如果我们的主存非常大,要分很多块群,是不是就大大增加了hit cache同一个槽的概率了
这也是直接映射的缺点
全映射
全映射是主存中任意一个块都可以映射到cache中的任意一个槽中,没有主存的某个块只能映射到cache的一个槽中的限制
因此,对于全映射的地址来说,主存地址中不存在cache槽号的内容
全映射访问方式:
假如CPU想访问主存0块中的12单元,CPU会从cache的0槽到15槽依次查看0块是否映射到cache中,如果都没有,主存才会将0块映射到cache中
试想一下,如果cache的槽号非常多,CPU每次要访问主存中的某个块里的单元,都要先将cache中的每个槽先查看一遍,是不是很浪费时间
组映射
组映射可以理解为是直接映射和全映射的结合体
在组映射中,会将cache进行分组,每组cache又会存在几个槽
组映射时,主存和cache的组之间映射是直接映射,与cache组中每个槽之间的映射时全映射
就像之前的例子,我们将cache的16个槽分为8组,每组有2个槽,那么在进行组映射的时候,主存在中块会先与cache的组进行直接映射,在确定要映射的组后,再与组内的两个槽进行全映射
这里地址中的标记位指出对应槽取自主存的哪个组群
联想刚才在全映射和直接映射提出的两个极端的情况:
- 如果主存很大(块多),主存的块hit cache同一个槽的概率增大,而在组映射的情况下,主存的块hit的是cache的组,而cache的组内有多个槽,主存的块可以存放在cache组内的任何一个槽中
- 如果cache很大(槽多),CPU要访问主存的某个块时,只需要先在cache的固定组中查看这个块是否存在即可
对比三种映射的地址
直接放图吧
标签:Cache,映射,cache,主存,访问,局部性,CPU 来源: https://www.cnblogs.com/ICcode/p/16496316.html