6.1 存储技术

1.随机访问存储器(RAM),是易失性存储器,掉电存储信息会丢失,与之相对的是非易失性存储器(ROM),它掉电后存储信息不丢失,但前者访问速度较快,但容量有限,通常只有几百或几千兆字节。

2.它分为静态RAM(SRAM)和动态RAM(DRAM),前者更快,价格也更高,密集度更低。

3.磁盘由盘片构成,一个盘片两个面,盘片中央有旋转轴以固定速率旋转,多个盘片组合并封装形成了一个磁盘,也就是所谓的机械硬盘。盘片可以被划分为许多同心圆,这些被称为磁道。每个磁道被分为许多扇区,每个扇区拥有相等数量的数据位,因此扇区的数量是由最靠内的磁道能记录的扇区数决定的,越靠外的磁道扇区隔得越开。扇区之间有间隙,不存储数据位,用于存储用来标识扇区的格式化位。如下图所示:

给个案例:假设有一个磁盘,有5个盘片,每个扇区512字节,每个面20000条磁道,每条磁道平均300个扇区,则其容量是多少?

答:容量为 5*2*20000*300*512 = 3.072*1010字节=30.72GB

4.对扇区的访问时间主要由以下3个部分组成:寻道时间(移动传动臂到对应磁道),旋转时间(定位到该磁道上的某个扇区)和传送时间(传送该扇区内容)

注意,由于并不知道扇区位于磁道中的那个地方,因此旋转时间通常用平均旋转时间来计算,即最大旋转时间/2。

给个案例:

解答:首先寻道时间是Tavg seek=5ms, 旋转速率是10000RPM,即10000转/分钟,那么最大旋转时间为(1/10000)*60*1000=6ms,平均旋转时间为3ms,1MB的文件约有2000个扇区,首先定位到第一个扇区,用了5+3=8ms,最优情况下直接顺序读两圈磁道即可,因此无额外的寻道和旋转时间,最终时间为8+2*6=20ms。而B对应的随机情况,每个扇区都要重新寻道和旋转定位,因此有2000*8 = 16s,差别巨大。这就是为什么需要清理磁盘碎片的原因。

6.2 局部性 略

6.3 存储器层次结构

如上图所示,是典型的存储器层次结构,从上往下越来越慢,越来越便宜和大。数据以块的形式在其中传输,每一级都可作为下一级的缓存,比如k+1级有序号为0-15的块,则k级可能会有0,2,7,9几个块作为缓存。块的大小不是固定的,较低层由于访问时间长,为了补偿这些较长的访问时间,倾向于使用较大的块。

如果要访问的内容在缓存中,则被称为缓存命中,若不在,则称为缓存不命中,要从下一层取出包含内容的块,若缓存满了,则要替换缓存中的某个块,替换策略有很多种,比如LRU(最近最少被使用)等。还有一种不命中叫冲突不命中,原因是由于下一层的某些块在映射到上一层的缓存时,使用了严格的映射策略,比如规定只能映射到i mod 4的块中,这样,块0,块4和块8都会映射到缓存中的同一个块,当程序先请求块0,再请求块4,块8时,即使缓存可以容纳多个块,每次访问也都会不命中。

6.4 高速缓存存储器

通过上图了解一下高速缓存中的几个重要参数:

每个存储器地址有m位,被分割为t位的标记位,s位的组索引位和b位的块偏移位。其中s位的组索引位把高速缓存分割成了2s个组,每个组有E行的高速缓存行,每行包含一个块,块的大小为2b个字节,b位的块偏移位可以指定选中的字节是从该块中的哪个字节开始计算。每一行还有个有效位,用于标记此行是否有效。

当每个组的行数E为1时,高速缓存被称为直接映射高速缓存。

考虑这样一个函数:

假设一个块是16个字节,高速缓存由两个组组成,且是直接映射高速缓存(因此整个大小为32字节),此时x[0]-x[7]存放在地址0-31,分别映射到组0和组1,y[0]-y[7]存放在地址32-63,也分别映射到组0和组1。如下图所示:

当访问x[0]时,由于缓存不命中导致x[0]-x[3]被加载到组0,访问y[0]时又会出现未命中,导致y[0]-y[3]被加载到组0,出现覆盖。同理,以后每次对x和y的访问都会由于覆盖出现未命中,这种现象被称为“抖动”。解决的方法是在数组后面加一定字节的填充,比如对以上情况,可以定义为float x[12],此时映射如下:

具体情况就不解释了。

考虑一个问题:为什么要用中间的位做索引位,而不是用高位?

答:当用高位做索引位时,相邻地址的内存块会映射到高速缓存的同一组,此时若顺序访问某个数组,那任何时刻高速缓存都只保存一个块的大小。使用效率很低。

给个例子:

对于A:假设有t位标记位,则每个组有2t个块。

对于B:由于S=512,所以索引位有9位,块大小为32字节,因此偏移位有5位,因此t=32-9-5=18位,因此每218个块会映射到同一组,而数组一共有4096*4/32=512个块,因此全部会映射到组0,因此任何时候,高速缓存最多只能保存一个块,效率很低。

当E>1时,高速缓存中的一个组可以包含很多行,每行存储一个块,它被称为组相联高速缓存,定位时找到组后要根据标识位进一步判断在哪一行。

当此高速缓存有很多行,但只有一个组时,它被称为全相联高速缓存。

对于高速缓存的写,有两个问题:

一个是对已经缓存了字的高速缓存,如何更新下一层的副本?

两种方法,一种是“直写”,即立刻把更新的高速缓存块写回到低一层中。第二种是“写回”,即尽可能推迟更新,只有当替换算法要驱逐这个更新的块时,才把它写到低一层中。

第二个问题是如何处理写不命中?

两种方法,一种是“写分配”,即加载相应的低一层的块到高速缓存,然后更新此高速缓存块。另一种是“非写分配”,即直接把这个字写到低一层。

给一些典型题:

答:对于A,由于块大小为8个字节,高速缓存总大小为16个字节,因此,一组可以存2个int,高速缓存总共可以存4个int,映射关系如下:

src [0][0] [0][1] 块1
[1][0] [1][1] 块2
dst [0][0] [0][1] 块1
[1][0] [1][1] 块2

访问src[0][0]时,不命中,于是读取src[0][0]和src[0][1]到块1中,此时块1是src[0][0]和src[0][1],块2为空。

随后访问dst[0][0],不命中,读取dst[0][0]和dst[0][1]到块1中,发生了覆盖,此时块1是dst[0][0]和dst[0][1],块2为空。

随后访问src[0][1], 由于之前发生了覆盖,所以不命中,读取src[0][0]和src[0][1]到块1中,又发生了覆盖, 此时块1是src[0][0]和src[0][1],块2为空。

随后访问dst[1][0],不命中,读取dst[1][0]和dst[1][1]到块2中,此时块1是src[0][0]和src[0][1],块2是dst[1][0]和dst[1][1]。

随后访问src[1][0],不命中,读取src[1][0]和src[1][1]到块2中,发生了覆盖,此时块1是src[0][0]和src[0][1],块2是src[1][0]和src[1][1]。

随后访问dst[0][1], 不命中,读取dst[0][0]和dst[0][1]到块1中,发生了覆盖, 此时块1是dst[0][0]和dst[0][1],块2是src[1][0]和src[1][1]。

随后访问src[1][1],命中。

随后访问dst[1][1],不命中,读取dst[1][0]和dst[1][1]到块2中,发生了覆盖,此时块1是dst[0][0]和dst[0][1],块2是dst[1][0]和dst[1][1]。

对于B:

当高速缓存为32字节时,可以存放4个块,则映射关系如下:

src [0][0] [0][1] 块1
[1][0] [1][1] 块2
dst [0][0] [0][1] 块3
[1][0] [1][1] 块4

显然此时只会在第一次访问块时才会有不命中,即一共只有4个不命中。

答:A:读总数=16*16*2=512

  B:整个缓存可以存1024/16=64个块,一个块可存两个结构体,grid共占用16*16/2= 128个块,因此grid的前8行正好全部映射到高速缓存中,后8行会

     进行覆盖映射。这里由于是顺序访问,每2个数据有1个不命中,不命中数=512*50%=256次

  C:50%

变种:

答:A:读总数仍为16*16*2=512

  B:由于这里是列访问,当访问前8个元素(即grid[0][0]-grid[7][0])时,都不命中,此时命中率50%,访问grid[8][0]-grid[15][0]时,会覆盖掉高速缓存,导致后面访问grid[0][1]-grid[7][1]时再次发生不命中,因此命中率一直维持在50%,因此不命中读总数为256。

C:50%

  D:高速缓存两倍大时,访问grid[8][0]-grid[15][0]不会覆盖掉高速缓存,又因为一个块可存两个结构体,因此后面访问grid[0][1]-grid[15][1]时会  命中,因此只存在冷不命中,不命中率只有25%。

再次变种:

答:A:512

 B:此时顺序访问,只有冷不命中,128。

 C:25%

 D:此时限制不命中率的不再是高速缓存大小,而是块大小,因为每个块只能存两个数据,因此此时不命中率仍是25%。

一道比较有意思的题:

答:

A:高速缓存能存放512/16=32个块,数组一共包含2*128*4/16=64个块,因此高速缓存最多存放数组的一行,然而数组是列访问的,访问x[0][0]时发生不命中并把x[0][0]-x[0][3]对应的块加载进来,随后访问x[1][0]时,发生不命中并把x[1][0]-x[1][3]对应的块加载进来,由于x[1][0]-x[1][3]映射的块刚好和x[0][0]-x[0][3]的相同,发生冲突不命中,会导致覆盖,导致随后访问x[0][1]时又会发生不命中,循环往复,不命中率100%。

B:翻倍后,高速缓存最多能把数组全部存放,因此x[1][0]-x[1][3]映射的块与x[0][0]-x[0][3]不同,不会发生覆盖,因此只会发生冷不命中,即每个块刚加载进来时对应的那次不命中,不命中率25%。

C:两路组相联时,一组有两行,即两个块,高速缓存最多存512/16/2=16组。此时x[0][0]-x[0][63]对应映射到组0-组15,首先访问x[0][0],将对应的块x[0][0]-x[0][3]加载到组0,随后访问x[1][0],此时x[1][0]-x[1][3]对应的块也会映射到组0,但由于每个组有两行,这个块会被加载到组0的第2行,循环往复,到访问完x[1][63]时,正好将高速缓存全部映射完,此时不命中率为25%,随后访问x[0][64]时,它对应的块也会映射到组0,根据LRU策略,会覆盖掉组0中对应x[0][0]-x[0][3]对应的那一行,即行1,同理,访问x[1][64]时,对应的块也会映射到组0,根据LRU策略,此时覆盖掉行2,因此按这种顺序访问不会发生立刻覆盖的情况,不命中率一直保持为25%。

D:不会,这种情况下,不命中已经是冷不命中了,增大高速缓存只能增加容纳的组的数量,但加载进来的每个块都只能容纳4个int,只能保证后面3个int能命中,命中率无法改善。

E:会,不解释了,看D就明白了。

再来一道:

首先,高速缓存可以存4*1024/16=256个块。

N=64时,数组的一行有64*4/16=16个块。对于sumA,由于顺序访问,只有冷不命中,25%。对于sumB,列访问,访问a[0][0]时,映射的块是块1,访问a[1][0]时,映射的块是块17,循环往复,到访问a[16][0]时,又会映射到块1,此时发生覆盖,如此继续,访问完a[63][0]时,对于任意一个块,发生了3次覆盖,因此,此时访问a[0][1]时,仍会发生不命中,同理,后面的情况也是如此,因此100%不命中。对于sumC,因为是按正方形的顺序访问的,在访问a[0][0]和a[1][0]时,要分别加载进来块1和块17,而访问a[1][0]和a[1][1]时,都会发生命中,因此最终不命中率50%,注意sumC中i是以2的速度递增的,不用担心有重复访问的问题。

N=60时,数组的一行有60*4/16=15个块。对于sumA,一样只有冷不命中,25%。对于sumB,列访问,对于第一列,从a[0][0]到a[59][0],此时映射的块分别为

1 16 31 46 61 76 91 106 121 136 151 166 181 196 211 226 241 256
15 30 45 60 75 90 105 120 135 150 165 180 195 210 225 240 255
14 29 44 59 74 89 104 119 134 149 164 179 194 209 224 239 254
13 28 43 58 73 88 103 118

无一重复,都不命中,而且此时不会发生覆盖,因此在继续访问a[0][1]到a[59][1]时,不会因为覆盖发生不命中,同理,后面也是这样,因此其行为类似于冷不命中,不命中率25%。

对于sumC,分析类似于sumB,也是25%。

CSAPP阅读笔记-存储器层次结构-第六章-P400-P462的更多相关文章

  1. Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十六章:实例化和截头锥体裁切

    原文:Introduction to 3D Game Programming with DirectX 12 学习笔记之 --- 第十六章:实例化和截头锥体裁切 代码工程地址: https://git ...

  2. UNP学习笔记(第二十六章 线程)

    线程有时称为轻权进程(lightweight process) 同一进程内的所有线程共享相同的全局内存.这使得线程之间易于共享信息,然后这样也会带来同步的问题 同一进程内的所有线程处理共享全局变量外还 ...

  3. CSAPP阅读笔记-32位64位的区别--来自第三章引言的笔记--P110

    仅从寻址上看,32位和64位机器能寻址的内存空间大小不同. 需要知道的是,计算机系统对存储器作了抽象,程序“认为”内存是一个很大的字节数组,然而实际上它是由多个硬件存储器和操作系统组合起来实现的. 程 ...

  4. CSAPP阅读笔记-struct, union, 数据对齐-来自第三章3.9的笔记-P183-P191

    1.数据对齐 为什么要对齐:通俗点解释就是CPU对数据访问时,每次都是取固定数量的字节数,假如一次取4个字节,若有个int存在0x01-0x04,则一次就能取出,若存在0x03-0x06,则需要分两次 ...

  5. CSAPP阅读笔记-汇编语言初探(数据传送类指令)-来自第三章3.2-3.3的笔记-P115-P128

    1.如何由机器代码生成汇编代码? objdump -d再加上文件名即可直接在终端看到由反汇编器恢复的汇编代码.注意,文件名并不一定得是.o文件,任何可执行文件都可以. 结果如下: 仅列举了反汇编tes ...

  6. CSAPP阅读笔记-gcc常用参数初探-来自第三章3.2的笔记-P113

    gcc是一种C编译器,这次我们根据书上的代码尝试着使用它. 使用之前,先补充前置知识.编译器将源代码转换为可执行代码的流程:首先,预处理器对源代码进行处理,将#define指定的宏进行替换,将#inc ...

  7. CSAPP阅读笔记-链接-第七章-P464-P500

    链接概述 经预处理器->编译器->汇编器处理后,源文件可被转化为一组可重定位目标文件,链接器将它们组合起来形成可执行文件. 每个可重定位目标文件由不同的“代码节”和“数据节”组成,每一个节 ...

  8. CSAPP阅读笔记-变长栈帧,缓冲区溢出攻击-来自第三章3.10的笔记-P192-P204

    一.几个关于指针的小知识点: 1.  malloc是在堆上动态分配内存,返回的是void *,使用时会配合显式/隐式类型转换,用完后需要用free手动释放. alloca是标准库函数,可以在栈上分配任 ...

  9. CSAPP阅读笔记-数组分配与访问-来自第三章3.8的笔记-P176-P183

    这一节比较简单,仅记录几个比较重要的点: 1.C语言允许对指针进行运算,计算出的值会根据该指针引用的数据类型大小进行伸缩. 例子: 其中,xE是数组的起始地址.注意,指针运算时,若最终结果为指针,则指 ...

随机推荐

  1. HDU 6125 Free from square (状压DP+背包)

    题意:问你从 1 - n 至多选 m 个数使得他们的乘积不能整除完全平方数. 析:首先不能整除完全平方数,那么选的数肯定不能是完全平方数,然后选择的数也不能相同的质因子. 对于1-500有的质因子至多 ...

  2. Introduction MBG

    文档地址 http://www.mybatis.org/generator/configreference/xmlconfig.html 源码地址 https://github.com/mybatis ...

  3. 设计模式18:Observer 观察者模式(行为型模式)

    Observer 观察者模式(行为型模式) 动机(Motivation) 在软件构建过程中,我们需要为某些对象建立一种“通知依赖关系”——一个对象(目标对象)的状态发生改变,所有依赖对象(观察者对象) ...

  4. Android PendingIntent小结

    官方文档的解释   A description of an Intent and target action to perform with it.   注意有一个target action,既Pen ...

  5. Window-document-javascript

    一个浏览器窗口有一个window对象,javascript属于window对象,html为document对象,属于window,body为document对象,只有设置body对象高度为100%,其 ...

  6. ArcGis Android 10.2.6更新文档翻译

    ArcGis Android 10.2.6更新文档翻译 @[ArcGis Android|10.2.6|更新文档] 本文描述了ArcGIS Runtime SDK for Android 10.2.6 ...

  7. Spring学习(三)——集成 Velocity

    上篇文章http://www.cnblogs.com/wenjingu/p/3822989.html我们使用Gradle构建了一个简单的Spring MVC Web应用程序, 本篇将在上篇的基础上将j ...

  8. php swoole扩展安装

    一波三折. 首先下载swoole安装包(由于我这里php是7,所以说应该去官网下载最新的swoole包,否则会发生意想不到的错误) wget https://github.com/swoole/swo ...

  9. coffee主题美化内容概要

    1.具备自动生浮动标题目录(可隐藏) 2.页首目录概要 3.主标题有明显的标志背景颜色,二级标题缩进合适 4.一级.二级标题下图片缩进合适 5.博客签名 6.背景音乐列表 7.打赏 8.联系方式(QQ ...

  10. 洛谷P3643 [APIO2016]划艇(组合数学)

    题面 传送门 题解 首先区间个数很少,我们考虑把所有区间离散化(这里要把所有的右端点变为\(B_i+1\)代表的开区间) 设\(f_{i,j}\)表示考虑到第\(i\)个学校且第\(i\)个学校必选, ...