Cache逻辑地址变换理解
为什么需要逻辑地址变换
某些数据需要存储在Cache(缓存中),那如何将主存数据和Cache的缓存数据联系起来,就需要通过地址变换,每个主存地址对应有Cache逻辑地址
自己的理解(大白话)
首先我们从自己的角度出发,如果我们想要将两者相联系,会作如何的设计,最简单的做法就是主存中一个地址,对应Cache一个地址,这样就相当于我们只需要记录相对于第一个初始地址的偏移,比如说我主存的物理地址1对应Cache的逻辑地址2,那我们就可以很轻易的得出,物理地址2对应逻辑地址3,但是这样就存在一个问题,我们一个个查是不是效率很低,所以我们设计一个结构来一块块的找,这个原理就好比,我们买菜不会从菜市场的头看到尾,我们会根据自己的需要找到卖某个菜的特定区域。所以相应的我们这里为主存定义了块这个单位,而Cache我们定义了行。
所以我们搞懂了它的由来,我们是不是就要确定他们如何来相匹配,最简单的方法就是,我要保证行和块的大小相同,如果不相同就要考虑上一个块和下一个块的差的大小如何补齐,是不是就很麻烦,那我们就干脆让他们的大小保证相同。确定了大小相同后,我们就要确定号之间如何对应
最简单的当然就是我根本不需要看号,有空的我就对应,比如我块号是1,我根本就不看行号是多少,只要他没有被别的块号占过,那我就跟他匹配,这就是全相联,那它是不是存在很明显的问题,就是我每次找没被占过的就需要从头开始找起,行号一多就会很费事
所以我们想到了另一个方法,就是我块号就是行号,那这样我是不是都不用看它占没被占过,我有块号就找到行号,原来被占了,我也可以把它淘汰掉,我自己占掉。这就是直接相联的原理。(引入了区号)
而组相联就是两者的结合,不同的是,这里引入了组号,行号的概念,那其实也一样,就是组好我对应,行号我随机。
理解了这三种方式再接下来看它的具体例子可能就会好理解很多。
常见的三种映射方式:
全相联
直接相联
组相联
三种方式的不同点理解
全相联
块号对应行号,全相联的块号是可以映射到Cache任意行的,每当一个块存储到Cache中时,都会在Cache有一个标志,保证下一次访问到同一个块的时候,就无需再进行标记
主存物理地址的构成方式
TAG + 块内地址
这里行的大小和块的大小相同
![](https://i-blog.csdnimg.cn/blog_migrate/209f50e3a66c775218f916a9e91b2327.png)
特点
Cache利用率高(一直到所有行都被利用满,才会出现冲突的情况)
块冲突率低
淘汰算法复杂
适用场合
小容量的Cache(因为需要进行反复的从头开始查询,所以对于大容量的Cache会消耗大量时间)
直接映射
与全映射的规则基本相同,但是这里的行号选择略有不同,不再是随机,而是映射到Cache特定行,如:Cache共n行,主存块j块号映射到Cache的行号为:
i = j mod n
而且直接映射相比于全映射又进行了分区,每区的行数为Cache的行数
主存地址
tag + index(块号)+ 块内偏移
![](https://i-blog.csdnimg.cn/blog_migrate/f49f1bdc59a1dd52b3d98be3ce068da1.png)
所以我们就很自然的想到,相比于全相联映射,多了一个区号,那这个区号要在主存地址中如何体现。
将原主存地址中的Tag作拆分,分别确定区号和行号
![](https://i-blog.csdnimg.cn/blog_migrate/7a92a2aa1dd0ce9e3d5b78c35e9b2696.png)
特点
Cache利用率低
快冲突率高
淘汰算法简单
应用场合
大容量的Cache
组相联
相比于之前的两个方式,增加了组,主存有组号,对应的Cache也有组号,但不同的是虽然组号是对应的,但是组内的行号却是任意匹配(从这个方面讲,它是兼有了前两种方式的特点)
![](https://i-blog.csdnimg.cn/blog_migrate/9d57c25eca7704b8e4556d8175797867.png)
特点
就是兼有了两者的,相当于两者的中间版