教材学习内容总结
在简单模型中,存储器系统是一个线性的字节数组,而cpu能够在一个常数时间内访问每个存储器位置。实际上,存储器系统是一个具有不同容量、成本和访问时间的存储设备的层次结构。书上有的内容我就不重复赘述了,只需要将部分重要的知识点归纳总结一下。
存储技术
静态RAM(SRAM):用来作为高速缓存存储器,每个位存储在一个双稳态的存储器单元里。双稳态就是说电路可以无限期的保持在两个不同的电压配置或者状态之一。只要供电,就会保持不变。即使有干扰,例如电子噪音来扰乱电压,当干扰消除后,电路就会恢复到稳定值。其
不需要刷新, 存取速度快 , 对光电噪声不敏感 ,晶体管多密集度低 ,功耗贵代价高 。
动态RAM(DRAM):用来作为主存以及图形系统的帧缓冲区。将每个位存储为对一个电容的充电,当电容的电压被扰乱之后,他就永远都不会再恢复了。暴露在光线下会导致电容电压改变。其
以纳秒为周期刷新,存取速度慢,光电因素易导致电压改变,电容小,密集度高, 功耗低。
电路设计者将DRAM组织成二维阵列,而不是线性数组的一个原因是
降低芯片上地址引脚的数量
。当然二维阵列组织的缺点是必须分两步发送地址,这 增加了访问时间。可编程ROM(PROM):只能被编程一次。PROM每个存储单元有一种熔丝,只能用高电流熔断一次。
可擦写可编程ROM(EPROM):紫外线光照射过窗口,EPROM就被清除为0,被擦除和重编程的次数为1000次。
电子可擦除ROM(EEPROM):不需要一个物理上独立的编程设备,因此可以直接在印制电路卡上编程,能够编程的次数为10^5。
闪存:基于EEPROM,为大量的电子设备提供快速而持久的非易失性存储。
磁盘结构(磁盘驱动器)结构:
盘片
、磁道
、扇区
、间隙
、柱面。
磁盘容量
访问时间:
寻道时间
、旋转时间
、传送时间
。逻辑磁盘块:内存可以看成字节数组、磁盘可以看成块数组,每一个逻辑块号可以翻译成一个(
盘面
,磁道
,扇区
)三元组。根据携带信号不同,总线可分为
数据总线
、地址总线
、控制总线
三种。CPU使用存储器映射I/O技术向I/O设备发出命令。
局部性
局部性有两种形式:
时间局部性
、空间局部性
。程序访问一个向量,步长越大空间局部性越差
。重复引用同一个变量的程序有良好的时间局部性; 对于具有步长为k的引用模式的程序,步长越小,空间局部性越好; 对于取指令来说,循环具有良好的时间和空间局部性。循环体越小,迭代次数越多局部性越好。
存储器层次结构
存储层次结构的中心思想是
上层作为下层的缓存
。利用时间局部性: 一旦一个数据在第一次不命中时被拷贝到缓存中,我们就会期望后面对该目标有一系列的访问命中。
利用空间局部性:块通常包含多个数据对象,我们通常期望后面对该块中其他对象的访问能够补偿不命中后拷贝该块的花费。
缓存不命中时,决定哪个块是牺牲块由
替换策略
来控制;空缓存的不命中叫强制性不命中
或冷不命中
;容量不命中的原因是缓存太小
。
高速缓存存储器
高速缓存结构可以用元组
(S,E,B,m)
来描述。高速缓存的大小C = S * E * B。
一个计算机系统每个存储地址有m位,形成M=2^m个不同的地址。
高速缓存被组织成一个有
S=2^s
个高速缓存组的数组,每个组包含E个高速缓存行,每个行是由一个B=2^b
字节的数据块、一位有效位以及t=m-(b+s)
个标记位组成,唯一标识存储在这个高速缓存行中的块。
学习过程
代码驱动的程序设计学习
git安装与gdb调试部分的内容在之前就完成了,这里主要展示tree的使用,使自己的代码管理更有条理。还有通过shell脚本来简化编译程序。
首先安装tree:
然后输入mkdir 20145326CSAPP2E 建立自己的代码文件夹“20145326CSAPP2E”,
输入cd 20145326CSAPP2E进入文件夹,建立相应的子文件夹。接着输入cd src进入文件夹,并创建12章相应的文件夹。
用tree查看:
在“ 01intro ”文件夹里新建一个“hello world”程序,然后运行。
最后就是git代码了。在这之前,要在码云新建一个项目“CSAPP2E”。
git成功后的效果:
然后按照这个过程,继续推送了本周剩余的代码。
通过shell脚本来简化编译运行程序
输入vim compile.sh, 进入编辑模式后,输入脚本。
输入chmod +x compile.sh给脚本添加可执行权限。
输入./compile.sh可以执行文件。
输入ls显示当前目录内容,我们可以使用.gitignore将不想纳入git管理的文件,文件夹都删掉。输入相应脚本内容,删掉bin。
实验楼作业(太有趣了!)
安装fortune:
练习题
习题6.2
计算这样一个磁盘的容量。它有2个盘片,10 000个柱面,每条磁道平均有400个扇区,每个扇区平均有512个字节。
磁盘容量 = (512/400)4001000022= 8 192 000 000 字节 = 8.192GB
习题6.3
估计访问下面的一个磁盘上的一个扇区需要的时间(以ms为单位)。旋转速率:15000RPM;Taveseek = 8ms;每条磁道的平均扇区数:500
访问时间 = Taveseek+Taverotation+Tavetransfer = 8ms +0.51/15000RPM60secs.min1000ms/s+1/15000RPM1/50060secs/min1000ms/s=8ms+2ms+0.008ms=10.008ms
习题6.4
假设1MB的文件由512字节的逻辑块组成,存储在有如下特性的磁盘驱动器上(旋转速率:10 000RPM,Taveseek=5ms,平均扇区/磁道 = 1000)。
(1)最好的情况:给定逻辑块到磁盘扇区的最好的可能的映射(即,顺序的),估计读这个文件需要的最优时间
(2)随机的情况:如果块是随机地映射到磁盘扇区的,估计读这个文件需要的时间
(1)T=Taveseek+Taverotation+2Tmaxrotation=5ms+3ms+26ms=20ms
(2)在这种情况下,块被随机的映射到扇区上,读2000块的每一块都需要Taveseek+Tavgrotation=8ms
。所以读这个文件的总时间为T = 8ms*2000=16000ms=16s
习题6.8
改变原函数中循环的顺序,使得它以步长为1的引用模式扫描三位数组a。
int sumarray3d(int a[N] [N] [N])
{
int i,j,k,sum=0;
for(k=0;k<N;k++){
for(i=0;i<N;i++){
for(j=0;j<N;j++){
sum += a[k] [i] [j];
}
}
}
return sum;
}
习题6.9
判断图中三个函数的空间局部性。
函数clear1以步长为1的引用模式访问数组,因此明显的具有最好的空间局部性;函数clear2依次扫描N个结构中的每一个,这也可以,但是在每个结构中,它以步长不为1的模式跳到下列相对于结构起始位置的偏移处,所以clear2的空间局部性比clear1的差;函数clear3不仅在每个结构中跳来跳去,而且还从结构跳到结构,所以clear3的空间局部性最差。
习题6.11
在前面dotprod的例子中,在我们对数组x做了填充之后,所有对x和y的引用的命中率是多少?
在对dotprod例子中对数组x定义为float x[12]
后,填充消除了冲突不命中,也就是不会发生y[0] ~ y[3]
的块被拷贝到组0,覆盖前一次引用拷贝进来的X的值的情况,因此有四分之三
的引用是命中的。
习题6.13
有两个低位是块偏移(CO)
,然后是三位的组索引(CI)
,剩下的位作为标记(CT)
。
m=13,B=4,b=2,S=8,s=3,t=m-b-s=8.所以有8个标记位,2位块偏移,剩下的位为组索引。
代码托管情况
把所有的代码都增加了详细的注释:
代码统计行数:
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 0/0 | 1/2 | 20/20 | |
第二周 | 58/58 | 1/3 | 20/40 | |
第三周 | 150/208 | 1/4 | 22/62 | |
第五周 | 150/358 | 1/5 | 21/83 | |
第六周 | 136/494 | 1/6 | 25/108 | |
第七周 | 115/609 | 1/7 | 24/132 |
心得体会
本周的学习内容主要是了解存储设备的类型和特点,以及局部性原理和缓存思想在存储层次结构中的应用,大部分的知识在前几章的学习中都或多或少有涉及到,比如存储的核心思想是每层存储设备都作为下一层的“缓存”等等,有了之前的基础,这一章的学习不是特别的吃力。静下心来,挨着一页页的看教材,边看边理解,收获还是比较大。学习完这部分知识后,我更清楚的了解了存储器的分类,更深入了解了数据传送的过程。要说难点的话,还是直接映射高速缓存运行过程的那部分知识,最开始觉得比较模糊,但是后面又学习到组相联高速缓存和全相联高速缓存时,把三种过程综合起来看就能够理解标记、组索引、块偏移各自的作用了。我一直认为完全不看教材,一心想走捷径是绝对不行的,要想有收获,必须投入大量时间与精力。最重要的还是摆正心态,不要应付,不要敷衍。我们应该挖掘学习的乐趣,享受学习的过程,这才是完美的。我会每周给自己定一个小目标~ 不断前进!!!争取早点获得娄老师颁发的奖品!哈哈哈!~