当前位置:网站首页>【你了解Cache吗——全面理解高速缓冲存储器】
【你了解Cache吗——全面理解高速缓冲存储器】
2022-07-26 22:50:00 【刘洋邑】
系列文章目录
1.《带你深挖计算机底层逻辑,打通你计算机基础知识的任督二脉》
2.《深度学习计算机底层原理,深度剖析存储器》
3.《基于内存全面理解高速缓冲存储器》
前言
你真的了解高速缓冲存储器吗?今天这篇文章带你对cache进行一个全面透彻的了解,我们不难知道,由于CPU和主存之间的性能差异越发明显,CPU的计算速度和访存速度差异太大,为了提高CPU的效率,我们引入了高速缓冲存储器,也就是我们上一篇文章所讲的静态RAM(基于双稳态触发器的六晶体管电路(MOS管)),高速度、低容量、高成本的特点。
cache属于存储器的一种,如果有对于存储器不太明白的小伙伴可以先浏览我本专栏的上一篇文章,相信你对存储器一定会有这更深的了解。
提示:以下是本篇文章正文内容,下面案例可供参考
一、程序访问的局部性原理
1.时间局部性原理:
时间局部性原理就是存储器在未来一段时间要访问的信息与现在访问的信息是相同的,也就是说,一个数据在将来的一段时间内会被重复访问,例如循环语句等,这种特征我们管他叫做时间局部性原理。
2.空间局部性原理:
空间局部性原理指我们所处理的信息的地址空间与未来要使用的信息的地址空间是临近的,因为计算机指令在执行的时候通常是顺序执行的。
3.示例:
请各位老铁仔细观察一下两段代码,他们的局部性原理如何啊
程序一:
include<stdio.h>
int func1(int arr[M][N])
{
int i=0;
int j=0;
int sum=0;
for(i=0;i<M;i++)
{
for(j=0;j<N;j++)
sum+=arr[i][j];
}
return sum;
}
注释:
首先我们来看第一个程序,论空间局部性原理的话,我们回想一下刚才提到的空间局部性原理的定义是什么?好我们紧接着看这个程序,通过观察我们不难知道,这个函数当中的sum在对数组在进行访问的时候,数组当中的每个元素是完全按照顺序来执行的,对吗?也就是说,程序现在所使用的数据的地址空间和未来要使用的地址空间是临近的,所以这个程序的空间局部性原理是很好的,起码比起第二个程序要好很多。
现在我们来观察他的时间局部性原理,有时间局部性原理可以分析,程序一数组当中的的每一个数据顺序执行,而且每一个数据只执行一次,所以他的时间局部性原理并不好,因为他做不到,程序未来要使用的信息和现在正在使用的信息相同。
程序二:
程序1:
include<stdio.h>
int func1(int arr[M][N])
{
int i=0;
int j=0;
int sum=0;
for(i=0;i<N;i++)
{
for(j=0;j<M;j++)
sum+=arr[i][j];
}
return sum;
}
注释:
经过程序一的分析相信大家已经能够很好的了解程序访问的局部性原理了,我们来分析程序二,程序二与程序一的最大的不同就是程序对于数组的访问形式,我们通过观察不难得出,如果把数组看作一个矩阵,程序二当中的数组访问顺序是arr[1][0],arr[2][0]....从中可以看出数组每次是跳跃式访问的,没访问一个数据,就要跳过一行,到下一行去访问。所以不难得出他的空间局部性原理是很不好的。
同样的时间局部原理呢?也不会,因为他当中没有循环,数据只使用一次之后再也不使用了,做不到程序未来使用的数据和现在使用的数据是相同的。
二、cache的基本工作原理
1.cache块
cache位于存储器结构的顶层通常由SRAM构成,cache块又称为cache行,每一块都有若噶奴字节组成,块的长度成为块长,由于cache的容量要远远小于主存,所以cache块的数量要远远的小于主存当中的的块数
cache块就是预测未来一段时间内CPU要访存(访存:CPU从内存当中访问数据)的数据,并将其装入cache块。这样子CPU就可以不用每次都到主存(内存)当中去访问了,直接到cache当中寻找想要访问的数据即可。
当CPU在cache当中找到想要访存的数据的时候,这里叫作cache块的命中,如果不命中的话,就必须要去主存当中把欲访问的数据取出来,然后再放入到主存,这样下次在访问这个数据的时候就可以直接到cache当中访问了,这样就大大地提高了CPU的访存效率。(cache块的命中率通常在95%以上)。
2.工作原理

原理详解:
- 当cpu想要访问主存的时候,通过控制总线(图中未画出)向主存发出控制信号,之后主存得到CPU想要访问主存的信号之后,主存会将CPU想要访问的主存当中的相应的存储单元的地址发送给CPU(存储单元的地址由块号和块内地址组成,因为主存本身是一块一块的所以有块号和和块内地址)。
- 将存储单元的物理地址发送给CPU以后,这个时候最关键的地方来了,这里有一个非常重要的中转机构“主存cache地址映射变换单元”,他的功能就是将主存当中的地址映射到cache块当中去。
- 这个时候CPU就会到经过地址转换以后的块地址当中去,查找有没有自己想要访问的数据,如果这个时候发现cache当中有自己想要访问的数据的时候(命中),会直接通过cache访问数据,这个时候就不需要再对主存进行访问了,这样就可以减少一次访存。(我们很多时候对会提到减少访存的次数,因为我们之前提到过CPU的运算速度远快于CPU访问主存的速度,所以减少一次访存可以节约很多时间,减少不必要的开销。)
- 那么如果这个时候没有命中呢?没有命中的话可以直接从主存当中将要经常要访问的数据调入cache块当中。
- 如果这个时候cache块已满,就需要通过“cache块替换机构”再结合相应的算法将原有的一些快替换出去,再把我们需要的块填装进来,至于替换的具体步骤以及算法是什么,我们后续马上为大家讲解。
- 不过到这里可能有小伙伴会问到,cache当中怎么会有CPU想要访问主存的数据呢,其实在这之前系统会通过对主存的扫描,挑选出CPU未来一段时间常用到的相应数据,并且提前放到cache当中,这也照应了我们之前提到过的程序访问的局部性原理当中的时间局部性原理,而且cache的命中率通常高达95%。
三、cache和主存的映射方式
温馨提示:
这里涉及到cache和主存之间进行信息交互的原理,是相对重要的一个部分,但很好理解,对于将来打算直接就业不打算考研的小伙伴对其原理了解即可,没有必要对其中的每一个具体运算过程都非常了解,而且面试题当中很少涉及,我们对他有一个初步的了解便于我们日后对于编程的深层次理解即可。
原理:cache行当中的信息其实就是主存当中的一个副本,地址映射就是把主存地址空间映射到cache地址空间,就是把存在于主存当中的某种信息按照一定的规则装入cache当中即可。
1.直接映射
主存当中的某一块位置只可以装载到cache块当中的唯一位置,一旦产生冲突,原有的快就会被踢出去
如果大家觉得抽象的话,我举一个例子大家就明白这个变态的映射方式了,为什么说他是变态呢?可以想象一下,你在坐公交车而且车上只有你一个人,你就相当于cache块当中原有的数据,这个时候,车上上来一个大爷,大爷二话不说直接冲到你的身旁让你给他让座,他还振振有词地说年轻人要礼让老年人,这个时候你会很惊讶,车上明明有那么多空位,可这老大爷却只对你的位置情有独钟,你说这是不是很变态呢?
说到这里想必大家就已经明白了,这个老大爷就相当于从主存调来的新的块,即使cache空间有很多空位,但是只要是他选上的块地址,不管有没有空位,原来的块都必须让开,这就容易发生激烈的块冲突,以及块的浪费。
2.全相联映射
那么全相联映射就很好理解了,主存当中的块可以到cache块当中的任意位置,也就是说老大爷不过会跟你抢座了,起码只要他有位置他就不会让你强行给他让座,这样就不会有太大的块冲突了。
但是还有一个问题,就是寻找的太慢了,就好比说,公交车上有1000个位置,但是做了999个人,“老大爷”会为了这一个座位寻找半天,这样子效率太低,“老大爷”也累得不轻啊。
3.组相联映射
组相联呢就好很多了,就是把cache块分成好几组,组间直接映射,组内全相联映射,也就是说,把公交车上分成好几个区域,“老大爷”随便找一个固定的区域不再换区,在区内在进行位置的寻找,这其实就是对于以上两种方式的有机结合。
结语:好了说到这里相信小伙伴们已经对于cache——主存的映射方式有了一个全面的了解,虽然举的例子有些生硬,但是可以帮助大家理解。
四、cache中主存块的替换算法
注释:其实这里就涉及到我们刚才提到的,万一在以上两种方法都试过以后,老大爷还是没有找到座位怎么办,这时候必须有人出来让座。
1.随机替换算法
顾名思义,随机替换呗,“老大爷”随机挑选一位幸(大)运(冤)儿(种)为他让座。
2.先进先出算法
最先上公交车的那个人让座,也就是最先被放到cache块当中的那个数组被踢出去。
3.近期最少使用算法
cache快当中,哪个数据用的最少,哪个数据用的最少,哪个数据最先被踢出去。
五、cache的写策略
注释:写策略就是当cache当中的内容被更新和修改时,必须保证cahce和主存当中的数据一致,因为CPU总是根据主存当中的数据地址映射到cache查找到相应的数据的,所以必须保证主存当中的数据和cache当中的数据一致。
1.全写法
当CPU对cache写命中时(在原有数据的基础上再写,也就是修改数据的意思),必须把数据同时写入主存和cache,原来的块(修改前)也不必再写入主存,直接由新块(修改后的块)将原来的块覆盖即可。
但是,这个时候遇到了一个问题就是,访存的次数被增加了,要知道CPU直接访问主存的时间损耗是很大的,那么为了减少这个时间损耗,我们就提出在CPU和主存之间的cache一旁设置一个写缓冲区,CPU将对cache修改后的数据写到写缓冲区,再由缓冲区写到主存。
不过这样会再次出现另一个问题,如果写的次数太频繁的话,缓冲区会溢出。
2.回写法
回写法就是等把事情办完以后回过头来再写,也就是当CPU修改cache中的数据时,不着急修改主存当中对应的值,而是等修改完这一块以后,先放着,等需要再次修改的时候,再把旧的值写到主存当中,起到一个转移保存的作用(这个时候已经修改了两次了,但是只进行了一次访存),这就明显地降低了CPU的访存次数
3.写未命中
刚才我们提到的时CPU写命中的情况,就是我要修改cache某块中的数据时,找到对应的cache块,但是写未命中就意味着,我要修改的这个数没有在cache块当中找到,那这个时候怎么办呢?这个时候我们提供两种方法。
- 写分配法:直接从主存当中加载这个块到cache中,然后再对cache块进行修改,之后就是重复刚才写命中时的步骤了。通常与回写法进行合用。
- 非写分配法:仅将其写入主存当中,不必进行调块,这个要与全写法进行合用。
总结
到此本篇文章的全部内容就讲解完毕了,希望和大家共同进步,也真心希望,各位友友们能够从我的文章当中有所收获,相信大家已经对高速缓冲存储器有所了解了,我的上一篇文章时专门讲述和存储器有关的概念的,如果大家还有不明白的地方,可以订阅的《计算机底层原理》专栏,在这里我将用心的为大家介绍操作系统、计算机网络、计算机组成原理等计算机底层的相关知识,那么下一篇文章将为大家介绍虚拟存储器和指令的相关概念。
你的支持就是我前进的最大动力,请问你学会了吗
边栏推荐
猜你喜欢

CAN总线通信应用

Nb-iot networking communication

TCP's three handshakes and four waves (brief introduction)

HCIP第一天静态路由综合实验

MySQL course 1. simple command line -- simple record welcome to supplement and correct errors

Lora communication application development

About unsafe problems such as fopen and strError encountered in vs2022 or advanced version running environment

Static routing default routing VLAN experiment

Hcip OSPF comprehensive experiment

C语言——二维数组、指针
随机推荐
Dynamic routing rip protocol experiment
NB-IOT联网通信
Open the door of programming
(史上最详细)Codeforces Round #805 (Div. 3)E. Split Into Two Sets
Lora网关节点汇聚传感器数据
C语言——二维数组、指针
WAN technology experiment
Brief introduction of VLAN principle and specific experimental configuration
MySQL course 2. Various queries of tables
HCIA静态路由基础模拟实验
Codeforces Round #796 (Div. 2), problem: (1688C) Manipulating History
Lora光照传感器节点数据采集
RISC-V工具链编译笔记
数字芯片的面积优化:第三届“华为杯”研究生创芯大赛数字方向上机题1详解
C language - characters and strings, arithmetic operators, type conversions
C语言——数组、字符串处理函数、strlen、strcpy和strncpy、strcat和strncat、strcmp和strncmp
HCIP-第二天
今天浅讲一下转义字符【萌新版】
Lora communication application development
RS-485总线通信应用