重学操作系统(四)

重学操作系统(四)

前言

这篇文章,记录下存储器相关的一些知识,涉及到L1 Cache,SSD,内存的一些问题。接下来还是贯穿全文的一个问题

SSD、内存和 L1 Cache 相比速度差多少倍?

存储器分级

为什么有存储器分级策略

因为我们希望的存储器是,体积小,空间大,功耗低,散热好,速度快。但是这种存储器是不存在的,现阶段,没有存储器能同时满足所有优点。

存储器分级策略

存储器分级

图片来源于参考一

上图很明显看出,存储器主要分6级。

寄存器

紧挨着CPU的控制单元和逻辑单元,所使用的材料也是最快的。存储速度快,能耗高,产热大,花费高。所以数量不能很多。

32位CPU中寄存器大多能存4个字节的内容

64位CPU中寄存器大多能存8个字节的内容

寄存器访问很快,一般要求半个CPU周期内完成读写。

L1-Cache

L1 缓存在CPU中,虽然它离CPU更近,但是它造价低,通常L1缓存大小在几十Kb到几百Kb,读写速度大概是2-4个CPU周期。

L2-Cache

L2缓存也在CPU中,但是比L1缓存离CPU远。它大小比L1缓存大,能达到几M,速度是10 - 20个CPU周期。

L3-Cache

L3缓存在CPU中,比L2缓存离CPU更远。大小通常大于L2缓存,可以达到十几或者几十M,读写时间是20 - 60个CPU周期。

内存

内存主要材料是半导体硅,主要插在主板上,距离CPU有一定的距离,需要总线,才能和CPU连接。它体积大,造价远低于前面的存储器。内存可以达到几G到几T这个范围的存储空间。它的读写速度是200 - 300个CPU周期

SSD和硬盘

SSD:固态硬盘,结构类似内存,但是断电后数据能保存。内存,缓存,寄存器,断电后数据消失。内存读写速度比SSD快了10 - 1000倍,而比硬盘快了大概100万倍。因此SSD逐渐取代硬盘。

当CPU需要内存中的某个数据,查询流程是:

寄存器(如果没有)-> L1缓存(如果没有)-> L2缓存(如果没有)-> L3缓存(如果没有)->内存

缓存条目结构

无论内存还是缓存,都是线性存储器,数据一个挨着一个存储。如果内存是一列表格,那么缓存是一个多列表格,每个表格中的每一行,叫做缓存条目。

方案

数学方法:
比如100个内存地址,但是10个缓存条目。内存地址编号0 - 999,缓存条目编号0 - 9。比如701编号的内存,用数学方法,通过”地址 % 缓存条目数”这种方式,确定它的缓存条目。

指令预读

由于CPU执行指令速度很快,一般2 - 6个周期能执行完毕,但是CPU读取内存速度,要200 - 300个周期,因此,CPU不能在内存中读一条指令就执行,如果这样,每个指令执行要200 - 300个周期。

解决方法:
将L1缓存分为指令区和数据区,为了避免数据缓存覆盖指令缓存。然后CPU把内存中的指令预读几十或者上百条,存到L1缓存。L1缓存读写速度是2 - 4个周期,因此可以跟上指令执行的速度。L2和L3不协助处理指令预读的问题,因此它们不需要被分为指令区和数据区。

缓存的命中率

和缓存命中相反的是,miss,缓存穿透。一般三级缓存的命中率在95%,只有大概5%的内存读取会穿透。

缓存置换

L1缓存满了,再次读内存,需要将旧条目移除,新条目存入,就叫缓存置换。

总结

回到开头的问题,我们可以得到,内存比SSD快10 - 1000倍,L1 Cache比内存快100倍。因此L1 Cache比SSD快1000 - 100000倍。

思考

假设有一个二维数组,共有1M个条目,如果遍历数组,是逐行遍历还是逐列遍历?
Answer:
逐行遍历,因为二维数组是每行是一个一维数组。元素存在一维数组内是连续的,因此逐行遍历,能一次将这些连续地址加载到缓存,提高了缓存命中率。并且逐行遍历,内存页交换次数会增加很多(最差情况,每遍历一个元素就交换一次)。这种情况可以通过增大物理内存解决。

参考

[1] https://kaiwu.lagou.com/course/courseInfo.htm?courseId=478&sid=20-h5Url-0&buyFrom=2&pageId=1pz4#/detail/pc?id=4610


 上一篇
重学操作系统(五) 重学操作系统(五)
重学操作系统(五)前言上面几篇文章,学习了关于计算机的基本理论,计算机原理,底层一些知识点。也算为我打开一扇大门。其中很多知识点和思想,都是曾经没学到的。之前几篇文章,让我受益匪浅。接下来几篇是介绍Linux指令相关的。Linux指令在面试
下一篇 
重学操作系统(三) 重学操作系统(三)
重学操作系统(三)前言之前面试遇到了递归转非递归的问题,当时把我难住了。今天就看到了相关的文章,悔不当初,应该早点看。现在就把这个文章总结下,加深记忆。 贯穿全文的问题:不支持递归的程序语言如何实现递归for循环执行int sum = 0;
  目录