从缓存角度来提高程序性能(一):存储器及缓存的概念

版权声明:转载请注明出处!谢谢! https://blog.csdn.net/qq_28114615/article/details/86569812

目录

1 常用的存储器

1.1 随机访问存储器(RAM)

1.2 磁盘

1.2.1 磁盘结构

1.2.2 磁盘容量

1.2.3 磁盘操作

2 存储器层次结构

3 缓存

3.1 什么是缓存

3.2 缓存命中与缓存不命中

 


1 常用的存储器

1.1 随机访问存储器(RAM)

       随机访问存储器分为两类:静态RAM和动态RAM。

       静态RAM也叫SRAM(Static RAM),SRAM的每一个存储单元由6个晶体管电路实现,该电路具有双稳态性,只要有电,即使有外界干扰,在干扰消失时也会马上恢复稳态;

       动态RAM也叫DRAM(Dynamic RAM),DRAM的每一个存储单元由1个电容和一个晶体管组成,其电路对干扰非常敏感,当电路状态被外界干扰扰乱后,就永远恢复不了了。而在电路中,由于多种情况会导致电路漏电,使得DRAM在10~100ms内失去电荷,所幸这段时间与计算机运行的时钟周期相比还是很长的,因此DRAM必须周期性地刷新电路,从而保持电路状态。

       SRAM与DRAM相比,其成本更高,密集度更低,访问速度更快。SRAM往往应用于Cache,而DRAM则应用主存、帧缓冲区等。不过不管是SRAM还是DRAM,都是需要有电才能维持,一旦掉电,存储的信息就消失了。

1.2 磁盘

1.2.1 磁盘结构

      磁盘相比于RAM,磁盘能够保存大量的数据,但是磁盘的访问速度则比RAM慢得多:比访问DRAM慢10万倍,比访问SRAM慢100万倍。磁盘的结构如下所示:

①磁盘是由盘片(platter)构成的,每个盘片有两个表面(surface),表面覆盖着磁性材料。盘片中央有一个可以旋转的主轴,使得盘片以固定的旋转速率旋转,通常是5400-15000转/分钟(Revolution Per Minute,RPM)。

②每个表面由磁道(track,一组同心圆)组成。

③每个磁道被划分为一组扇区(sector),每个扇区包含数量相等的数据位,这些数据编码在扇区上的磁性材料中。

④扇区之间由一些间隙(gap)分隔,间隙存储用来标识扇区的格式化位。

⑤柱面(cylinder):所有盘片表面上到主轴中心的距离相等的磁道的集合。

1.2.2 磁盘容量

      根据前面的分析可知,磁盘容量即是磁盘存储的数据大小,可以得出磁盘容量的计算公式如下:

磁盘容量 = 字节数/扇区 × 扇区数/磁道 × 磁道数/表面 × 表面数/盘片 × 盘片数/磁盘

      需注意的是,这里的字节数/扇区是指的每个扇区上的字节数,而不是字节数除以扇区数。

      举个例子,计算一个磁盘的容量,它有两个盘片,10000个柱面,每条磁道平均有400个扇区,而每个扇区有512个字节。

      直接代入公式,磁盘容量 = 512×400×10000×2×2 = 8.192GB

1.2.3 磁盘操作

       磁盘的读写操作时通过读写头实现的,每个盘面上都有一个读写头,并且所有读写头都是垂直排列,同步行动,在任何时刻,读写头都位于同一个柱面上。如图所示。

                          

       磁盘是以扇区大小的块来进行读写数据,对扇区的访问时间主要由三部分组成:寻道时间、旋转时间和传送时间。

       为了读取目标扇区的数据,那么就需要先找到目标扇区,而要找到目标扇区,就需要先找到目标扇区所在的磁道。读写头移动到指定磁道所花的时间就叫寻道时间T_{avg seek},通常为3~9ms;

       读写头找到指定磁道后,就需要找到目标扇区了,在指定磁道上寻找目标扇区的时间就叫旋转时间T_{avg rotation},最好情况下,读写头刚刚寻道结束就落在了目标扇区上,此时旋转时间即为0,最坏情况下,读写头寻道结束后刚好错过目标扇区,那么就还需要等磁盘再转一圈才能找到目标扇区,这个时间刚好就是磁盘转一圈所花的时间,因此,平均旋转时间=磁盘旋转一圈的时间÷2;

       读写头找到目标扇区后,就开始读或者写扇区的数据了,这个阶段所花的时间就叫传送时间T_{avg transfer},而传送时间其实就可以理解为读写头扫过一整个扇区所花的时间。由于一个磁道上的扇区都是平均分布的,因此磁盘转一圈的时间就相当于将磁道上所有扇区都扫过的总时间,那么将其除以磁道上的扇区数,就是扫过一个扇区所花的时间了。因此,传送时间=磁盘旋转一圈的时间÷扇区数。

       举个例子,某磁盘的旋转速率为7200RPM,寻道时间为9ms,每条磁道的平均扇区数为400,求磁盘的平均访问时间。

        首先,寻道时间为9ms是已知的,然后就是旋转时间,根据磁盘的转速求出其旋转时间为(1/2)*(60/7200)≈4ms,再求得其传送时间为(60/7200)*(1/400)≈0.02ms,因此整个访问时间大概为T=9ms+4ms+0.02ms=13.02ms。

2 存储器层次结构

        我们知道,当程序运行后,代码会被加载到内存中,然后CPU从内存中取出指令并执行。但是实际上,不同存储技术的访问时间差异很大,往往容量越小的存储设备,其访问速度越快,当然成本也就越高;容量越大的存储设备,其访问速度就越慢,成本也就越低。如果让CPU直接从CPU里的寄存器访问数据,可能只需花费一个时钟周期即可;而如果让CPU直接从内存中访问数据,那就可能需要花几十或几百个时钟周期才行。并且随着技术的发展,CPU和主存之间的速度差距越来越大,如果仍然让CPU直接访问内存,那么CPU就需要长时间等着访问数据的结束,而这个等待的时间CPU可以做很多事情,这样明显就降低了CPU的效率。

       为了降低这种情况带来的影响,就在CPU和主存之间加上一个小而快的设备,这个设备就叫高速缓存(cache),CPU访问这个设备比直接访问主存快得多得多,这个设备就作为主存的数据对象的缓冲区域,CPU会先从cache中访问需要的数据,如果没有再去主存中找,一旦CPU从主存中访问到了某个数据,那么这个数据的副本便会保存在cache中。

       虽然cache可以在一定程度上避免CPU直接访问主存,但是随着CPU与主存之间的性能差距越来越大,一片cache显然是不够的,因此就在CPU和主存中再插入cache,这样就有了一级高速缓存、二级高速缓存、三级高速缓存甚至四级高速缓存,而这些缓存之间的大小和访问速度也是有差异的。典型的存储器层次结构图如图所示:

               

        在整个结构中,最上面的是L0,这一类是CPU中的寄存器,访问速度极快,通常CPU可在一个时钟周期内访问它们;然后是L1高速缓存,它和寄存器的访问速度几乎一样,典型的访问速度大概是4个时钟周期;接下来就是L2高速缓存,它的容量比L1更大,当然访问速度也就更慢了,大概可以在10个时钟周期内访问到它;有的系统中还会在L2高速缓存中插入L3高速缓存,它拥有比L2更大的容量,但是访问速度降到了50个时钟周期左右;接下来就是主存、磁盘以及远程存储等了,越往下容量越大,但访问速度越慢。

3 缓存

3.1 什么是缓存

        前面说过,高速缓存中存储着更大、更慢设备中数据的副本,使用高速缓存的过程就称为缓存。在存储器层次结构图中,对于每个k,位于k层的更小更快的存储设备都作为位于k+1层的更大更慢的存储设备的缓存。换句话说,层次结构中的每一层都缓存这来自较低一层的数据的副本。例如,主存作为磁盘的缓存,L1作为L2的缓存,寄存器作为L1的缓存等等。

       数据从第k+1层复制到第k层,是以块大小为传送单元的,任意一对相邻的层次之间块大小是固定的,但是不同相邻层次之间的块大小是可以不同的。比如,L1与L0之间传送的块大小为1个字节,而L2和L1之间传送的块大小为几十个字节。

3.2 缓存命中与缓存不命中

       什么是缓存命中呢?如果CPU需要第k+1层中的某个数据d时,它就会先在第k层中中寻找d,如果正好第k层中有d,那么这就叫缓存命中,按照前面所说,访问第k+1层的速度必定是比访问第k层慢的,因此,缓存命中会加快数据的访问,从而提高效率。

        而对于缓存不命中,当然就是指的第k层中没有数据d了,当发生缓存不命中时,那么第k层就会从第k+1层中取出包含d的那个块,如果此时第k层的缓存已经满了,就会用含d的那个块覆盖第k层中的某个块。那么到底覆盖哪个块呢?这就是个策略选择的问题了,如果是随机替换策略的话那就是用含d的块替换第k层中随机的一个块;如果是LRU替换策略的话,就是用含d的块替换掉最后一次使用最久远的块;如果是LFU替换策略的话,就是用含d的块替换掉使用频率最少的块。

        另一方面,如果第k层的缓存是空的,那么访问任何数据都不会命中,这种不命中称为强制性不命中或冷不命中;还有一种就是不同数据在第k层的缓存中映射到同一个缓存块,那么缓存也不会命中,此时就会根据替换策略来放置该数据,这种不命中叫冲突不命中。

 本文主要总结了一些相关概念,主要参考《深入理解计算机系统》一书。

 

猜你喜欢

转载自blog.csdn.net/qq_28114615/article/details/86569812