- 存储器层次结构
- 存储器差异
- 缓存类型
- 磁盘读取
- 补充练习
- 缓存存储器的组织和操作
存储器层次结构
存储器差异
首先我们必须认识到不同存储器之间的效率差异,见下图:
主存,一般就是我们常说的内存,其通常为DRAM(动态随机访问存储器),具有断电后不保存的特性,其访问速度远高于Disk类的断电仍保存的存储器;
但相较于CPU寄存器,内存的效率又慢了许多。
基于不同存储技术访问时间的差异很大,我们能够得到下图所示的存储器层次结构:
往上访问速度快的技术成本更高,其存储容量更小,像CPU寄存器,一级缓存二级缓存等等;
往下访问速度越慢成本低,存储容量越大,像本地磁盘,网盘等等。
根据这种规律,位于第K层的更小更快的存储设备可以作为位于第k+1层的更大更慢的存储设备的缓存,来节约时间提高效率。
简单介绍一下缓存:
缓存:一种较小,速度较快的存储设备,可作为存储设备的暂存区较大,较慢的设备中的数据子集。
对于第k+1层存储器,其被划分为连续数据对象组的块,对k层亦然。
只不过第k层的块少于第k+1层,而k层缓存应包含k+1层块的子集数据副本(通常相邻层次块大小固定,不同层次间可有不同大小的块)
局部性原理:具有局部性原理的程序倾向于使用,那些接近或等于他们最近使用过的那些数据和指令,这种局部性包括空间局部性和时间局部性。
一个好的程序总是保持这良好的局部性。
局部性好的程序就是充分地利用了存储的缓存机制。
空间局部性(命中相邻)
时间局部性(再次命中)
简单demo:
for(int i = 0;i < M;++i){
sum += v[i];
//其中sum常用,对于时间局部性,i为索引,步长为1很小,对应空间局部性
}
缓存类型
对于缓存命中hit,即当前访问数据无需从慢的k+1层存储访问,直接从第k层缓存读取。
若缓存miss,则仍需要访问k+1层储存获取数据,然后将新数据放入k层缓存;
倘若k层缓存已满,则需要根据一定的替换策略来覆盖某些块为新数据。
对于缓存不命中,我们根据其原因分为三类:
- 冷不命中:对块的首次访问必须错过,大多数冷未命中发生在开始时,因为缓存开始为空
- 冲突不命中:考虑到k层缓存比k+1层容量小,我们数据块一般会进行映射,当k层高速缓存足够大,而所有数据对象都映射到同一级别k块时,就会发生冲突未命中,举个例子:我们把k+1层块进行编号,第 i 块 mod 4 放入k层缓存,当我们不断进行0,8,0,8,0,8…一系列的访问,缓存将持续冲突不命中,因为0和8号块都会被映射在k+1层的同一个数块上(即mod 4 = 0),它们轮流占据同一个缓存位置。
- 容量不命中:当活动缓存块的集合大于缓存时发生,即缓存太小无法处理工作集。
磁盘读取
磁盘驱动器:
磁盘常常考到的是磁盘读取的时间,过程示例如下:
磁盘一般读取某块数据用时主要包括三个时间:
- 寻道时间:主要是将磁头定位在包含目标扇区的圆柱体上的时间,一般直接给或者是
磁道数*平均移动时间。 - 旋转时间:等待旋转至目标扇区的第一位在读/写头下通过的时间,注意:这里一般会给一个转速 例如6000转/min,我们一般计算平均旋转时间 Tavg rotation = 1/2 x 1/RPMs x 60 sec/1 min
对于6000r/min ====> 60 / 6000(每秒转多少圈) * 1/2(平均旋转) * 1000(一般转化为ms) = 5ms - 读取时间:读取目标扇区中的数据的时间。Tavg transfer = 1/RPM * 1/(avg # sectors/track 一个磁道平均多少扇区,实际上是计算旋转了多少圈) * 60 secs/1 min.
例如:6000r/min 每个磁道100个扇区 读取时间 = 60/6000 * 1 / 100 * 1000 = 0.1ms
补充练习
设某单面磁盘旋转速度为每分钟 6000 转,每个磁道有 100 个扇区,相邻磁道间的平均移动时间为 1ms。若在某时刻,磁头位于 100 号磁道处,并沿着磁道号增大的方向移动(如下图所示),磁道号请求队列为 50,90,30,120(采用电梯调度),对请求队列中的每个磁道需读取 1 个随机分布的扇区,则读完这 4 个扇区点共需要多少时间 ?
可以发现实际上耗时最长的还是寻道时间和旋转时间,而旋转时间用硬件决定难以优化,因此一般优化磁盘臂调度策略。
缓存存储器的组织和操作
通常缓存组织形式为组,每组内有若干行行:
一般而言地址分为三块 SEB:
对于缓存而言有:
先看组索引,再看标志位和有效位看是否组内有匹配行,若命中,再看块偏移;不命中从k+1层取出块并替换k层某块;
不同的缓存存储类型:
- 直接映射高速缓存——每组仅有一行(E = 1)
- 由于组内仅有一个行,比较tag,若match则命中,再找块偏移。
- 组相联高速缓存——E > 1
- 与直接映射高速缓存差异不大,只不过这里组内多行,都比较找tag是否match
- 全相联高速缓存——只有唯一一个组,地址中没有组索引了
注意写回问题:
L1,L2,主内存,磁盘可能存在多个数据副本:
高速缓存与原副本之间的更新问题,直写方式为 写命中时更新的缓存数据立即写入内存;写回方式为 脏页被替换策略替换时才写回
基本了解了缓存原理,这就要求我们编程时保持良好的局部性原理,提高缓存命中效率。