2017-2018-1 20155306 《信息安全系统设计基础》第13周学习总结
2017-2018-1 20155306 《信息安全系统设计基础》第13周学习总结
教材学习内容总结
内容要点总结:第6章 存储器层次结构
在简单模型中,存储器系统是一个线性的字节数组,而CPU能够在一个常数时间内访问每个存储器位置。实际上,存储器系统是一个具有不同容量、成本和访问时间的存储设备的层次结构。CPU寄存器保存着最常用的数据。靠近CPU的小的、快速的高度缓存存储器作为一部分存储在相对慢速的主存储器中的数据和指令的缓冲区域。 存储器层次结构是可行的。
6.1 存储结构
6.1.1随机访问存储器
随机访问存储器分为两类:静态的(SRAM)和动态的(DRAM)。
1)静态RAM
SRAM将每个位存储在一个双稳态的存储单元里。只要有电,他就会永远保持他的值。即使有干扰来扰乱电压,当干扰消除时,电路就会恢复稳定值。
2)动态RAM
DRAM将每个位存储为对一个电容的充电。与SRAM不同,DRAM存储单元易受干扰。当电容的电压被扰乱后,他就永远不会恢复了。
SRAM和DRAM的特性:
1.只要供电SRAM就会保持不变。
2.SRAM的存取比DRAM快。
3.SRAM对干扰不敏感。
4.SRAM单元比DRAM单元使用更多晶体管,密度较低,更贵,功耗更大。
AM
- 行地址i:RAS
- 列地址j:CAS
- DRAM组织成二位阵列而不是线性数组的一个原因是降低芯片上地址引脚的数量。
- 二维阵列组织的缺点是必须分两步发送地址,这增加了访问时间。
4)存储器模块
- DRAM芯片包装在存储器模块中,他是插到主板的扩展槽位上的。常见的包括168个引脚的双列直插存储器模块,以64位为块传送数据到存储控制器和从存储控制器传出数据,还包括72个引脚的单列直插存储器模块,以32位为块传送数据。
- 通过将多个存储器模块连接到存储控制器,能够聚合主存,当控制器收到一个地址A时,控制器选择包含A的模块k,将A转换为它的(i, j)的模式,并将(i, j)发送到模块k。
5)增强的DRAM
- 快页模式DRAM(FPM DRAM):异步控制信号,允许对同一行连续的访问可以直接从行缓冲区得到服务。
- 扩展数据输出DRAM(EDO DRAM):异步控制信号,允许单独的CAS信号在时间上靠的更紧密一点。
- 同步DRAM(SDRAM):同步的控制信号,比异步的快。
- 双倍数据速率同步DRAM(DDR SDRAM):使用两个时钟沿作为控制信号,使DRAM速度翻倍。
- Rambus DRAM(RDRAM):一种私有技术 。
- 视频RAM(VRAM):用在图形系统的帧缓冲区中。
6)非易失性存储器
- 如果断电,DRAM和SRAM会丢失他们的信息,所以他们是易失的。
- 非易失性存储器,即使是在关电以后,也仍然保存着他们的信息。他们整体上都称为只读存储器(ROM)。
- ROM以他们能够被重新编程的次数和对他们进行重编程所用的机制来区分的。
- PROM 只能被编程一次。
- 可擦可编程ROM,有个透明的石英窗口,允许光到达存储单元。
- 闪存,是一类非易失性存储器,基于EEPROM,他已经成为了一种重要的存储技术。
- 存储在ROM中的程序通常称为固件。
7)访问主存
- 数据流通过称为总线(bus)的共享电子电路在处理器和DRAM主存之间来来回回。每次CPU和主存之间的数据传送都是通过一系列步骤来完成的,这些步骤称为总线事务。
- 读事务:从主存传送数据到CPU
- 写事务:从CPU传送数据到主存
- 总线:一组并行的导线,能携带地址、数据和控制信号。
- 每个网络应用都是基于客户端-服务器模型的。
- 一个应用是由一个服务器户端提供某种服务。服务器管理某种资源,并且通过操作这种资源来为它的客户端提供某种服务。
- 客户端-服务器模型中的基本操作是事务。
四步组成:
- 当一个客户端需要服务时,它向服务器发送一个请求,发起一个事务。
- 服务器收到请求后,解释它,并以适当的方式操作它的资源。
- 服务器给客户端发送一响应,并等待下一个请求。
- 客户端收到响应并处理它。
#### 6.1.2磁盘存储
磁盘是保存大量数据的存储设备。
1)磁盘构造
磁盘是由盘片构成的。每个盘片有两个盘面,表面覆盖着磁性记录材料。盘片中央有个可以旋转的主轴,使得盘片以固定的旋转速率旋转。
![](http://images2017.cnblogs.com/blog/1071554/201711/1071554-20171119182815546-590006546.jpg)
- 旋转速率:通常5400~15000/min
- 磁道:同心圆们
- 扇区:每个磁道被划分为一组扇区
- 数据位:每个扇区包含相等数量的~,通常为512字节
- 间隙:存储用来标识扇区的格式化位
- 磁盘驱动器-磁盘-旋转磁盘
- 柱面:所有盘片表面上到主轴中心的距离相等的磁道的集合。
2)磁盘容量
![](http://images2017.cnblogs.com/blog/1071554/201711/1071554-20171119182838874-1011265145.jpg)
计算磁盘容量的公式:
磁盘容量 = 字节数/扇区 X 平均磁盘数/磁道 X 磁道数/表面 X 表面数/盘片 X 盘片数/磁盘
3)磁盘操作
磁盘以扇区大小的块来读写数据。
访问时间的分类:
(1)寻道时间:
——移动传动臂所用的时间。
依赖于读/写头以前的位置和传动臂在盘面上移动的速度。
通常为3-9ms,最大可达20ms。
(2)旋转时间
——驱动器等待目标扇区的第一个位旋转到读/写头下
依赖于盘面位置和旋转速度。
最大旋转延迟=1/RPM X 60secs/1min (s)
平均旋转时间是最大值的一半。
(3)传送时间
依赖于旋转速度和每条磁道的扇区数目
平均传送时间= 1/RPM x 1/(平均扇区数/磁道) x 60s/1min
访问一个磁盘扇区内容的平均时间为平均寻道时间,平均旋转延迟和平均传送时间之和。
3)逻辑磁盘块
磁盘结构抽象成B个扇区所组成的逻辑序列,编号位0-(B-1),在磁盘中,有一个小的硬件/固件设备,称为磁盘控制器。
![](http://images2017.cnblogs.com/blog/1071554/201711/1071554-20171119182900640-352292124.jpg)
4)连接到I/O设备
- 像图形卡、监视器、鼠标键盘和磁盘这样的输入/输出(I/O)设备,都是通过I/O总线连接到CPU和主存的。
- 虽然I/O总线比系统总线和存储器总线慢,但它可以容纳种类繁多的第三方I/O设备。
5)访问磁盘
- DMA:直接存储器访问
——设备可以自己执行读或者写总线事务,而不需要CPU干涉的过程。
#### 6.1.3固态硬盘(SSD)
- 一个SSD包由一个或多个闪存芯片和闪存翻译层组成,闪存芯片代替传统旋转磁盘中的机械驱动器,而闪存翻译层是一个硬件/固件设备,扮演与磁盘控制器相同的角色,将对逻辑块的请求翻译成对底层物理设备的访问。
- 随机读和写的性能差别是由底层闪存基本属性决定的。
#### 6.1.4 存储技术趋势
不同的存储技术有不同的价格和性能折中
不同存储技术的价格和性能属性以截然不同的速率变化着
增加密度从而降低成本比降低访问时间更容易
DRAM和磁盘的性能滞后于cpu的性能
### 6.2局部性
一个编写良好的计算机程序通常具有良好的局部性。他们倾向于引用邻近于其他最近引用过的数据项的数据项,或者最近引用过的数据项本身。这种倾向称为局部性原理,局部性原理对硬件和软件系统的设计和性能都有着极大的影响。局部性有两种不同形式:时间局部性和空间局部性。有良好局部性的程序比局部性差的程序运行的更快。
#### 6.2.1 对程序数据引用的局部性
![](http://images2017.cnblogs.com/blog/1071554/201711/1071554-20171119182917359-1879081411.jpg)
#####下面我们来看一些例子:
int sumvec(int v[N])
{
int i, sum = 0;
for (i = 0; i < N; i++)
sum += v[i];
return sum;
}
分析:首先,看sum变量,它在每次循环中都会被引用,因此,对于sum来说,具有好的时间局部性,但是没有空间局部性。
再看数组v的元素是顺序排列的,因此对于数组v,具有良好的空间局部性。但是时间局部性较差。
所以,综合看来这个程序具有良好的局部性。
int sumarrayrows(int a[M][N])
{
int i, j, sum = 0;
for (i = 0; i < M; i++)
for (j = 0; j < N; j++)
sum += a[i][j];
return sum;
}
分析:这个函数的引用是步长为1的,因为它按照数组被存储的行优先顺序来访问的。具有很好的空间局部性。
int sumarraycols(int a[M][N])
{
int i, j, sum = 0;
for (j = 0; j < N; j++)
for (i = 0; i < M; i++)
sum += a[i][j];
return sum;
}
分析:该代码只是把之前代码作很小的改动,程序的访问并不是按照行优先顺序的,因为C数组在存储器中是行优先的,所以,他的步长是N,空间局部性很差。
6.2.2 取指令的局部性
循环体里的指令是按照连续的存储器顺序执行的,因此循环有良好的空间局部性,因为循环体会被执行多次,所以它也有良好的时间局部性。
代码区别于程序数据的一个重要属性时在运行时是不能被修改的。
6.2.3 局部性小结
量化评价一个程序中局部性的简单原则:
- 重复引用同一个变量的程序有良好的时间局部性
- 对于具有步长为k的引用模式的程序,步长越小,空间局部性越好
- 对于取指令来说,循环有好的时间和空间局部性。循环体越小,循环迭代次数越多,局部性越好。
6.3 存储器层次结构
图片展示的是便是存储器的层次结构,所有的现代计算机系统中都采用这种方法。
一般而言,从上到下,存储设备变的更慢,更便宜,容量更大。
高层是寄存器,可以在一个时钟周期内访问;
接下来是一个或者多个的基于SRAM的高速缓存存储器,可以在几个CPU时钟周期内访问;
下面是基于DRAM的主存,可以在几个到几百个时钟周期内访问到;
接下来是慢速但容量很大的磁盘系统,最后还有远程网络上的存储器系统。
缓存:使用高速缓存的过程被称为缓存。
存储器层次结构的中心思想:k层的更小更快的存储设备,作为k+1层的更大更慢的存储设备的缓存。也就是说,层次结构中的每一层都缓存来自较低一层的数据对象。
6.3.1 存储器层次结构中的缓存
高速缓存:是一个小而快速地存储设备,它作为存储在更大、也更慢的设备中的数据对象的缓冲区域。 缓存:使用高速缓存的过程。
1)缓存命中
但程序需要第k+1层的某个数据对象d时,它首先在当前存储在第k层的一个块中查找d,如果d刚好缓存在第k层中,那么就是我们说的缓存命中。
2)缓存不命中
- 若第k层中没有缓存数据对象d,那么就是我们所说的缓存不命中。
- 替换或驱逐:覆盖一个现存的块的过程。
- 牺牲块:被驱逐的这个块。
- 替换策略:决定应该替换哪个块。
3)缓存不命中的种类
-
冷缓存(强制不命中\冷不命中):一个空的缓存,对于有效位为0的情况 。 缓存暖身:反复访问存储器使缓存暖身之后的稳定状态
-
冲突不命中:限制性的放置策略会引起的一种不命中。 若发生了不命中,第k层的缓存就必须执行某个放置策略,确定把它从第k+1层中取出来的块放在哪里。 硬件缓存通常使用的是更严格的放置策略。例如:第k+1层的块0、4、8、12会映射到第k层的块0;块1、5、9、13会映射到块1;以此类推。
-
容量不命中:当工作集的大小超过缓存的大小时。工作集:程序是按照一系列阶段来运行的,每个阶段访问缓存块的某个相对稳定不变的集合。
4)缓存管理
缓存管理:某个东西要将缓存划分成块,在不同的层之间传送块,判定是命中还是不命中,并处理它们。
- 编译器管理寄存器文件,缓存层次结构的最高层。
- L1、L2、L3层的缓存完全是由内置在缓存中的硬件逻辑来管理的。
- DRAM主存是有操作系统软件和CPU上的地址翻译硬件共同管理的。
- 每个以太网适配器都有—个全球唯一的48位地址,它存储在这个适配器的非易失性存储器上。一台主机可以发送一段位,称为帧。每个主机适配器都能看到这个帧,但是只有目的主机实际读取它。
这个图展示了存储器层次结构中缓存的一般性概念。可以看到,第k+1层的存储器被划分成连续的数据块。每个块都有一个唯一的地址或名字,使之区别于其他的块。块可以是固定大小的,也可以可变大小的。例如,第k+1层存储器被划分为16个大小固定的块,编号为0—15。
类似的,第k层的存储器被划分较小的块的集合,每个块的大小与k+1层的块的大小一样。在任何时刻,第k层的缓存包含第k+1层块的一个子集的拷贝。例如,在图中,第k层缓存中有4个块的空间。当前包含块4,9,14和3的拷贝。
eg.如上图所示,思考这么几个问题:在第k层读取块4中的一个数据对象,是什么结果?在第k层中读取块12中的一个数据对象,是什么结果?在读取块4之后,读取块12,然后再读取块4,是什么结果?
答案:依次产生上面所讲的缓存命中,缓存不命中,缓存不命中(冲突不命中)。
6.3.2 存储器层次结构概念小结
存储结构的本质:每一层存储设备都是较低一层的缓存。
概括来说,基于缓存的存储层次结构行之有效,是因为较慢的存储设备比较快的存储设备更便宜,还因为程序倾向于展示局部性。
-
利用时间局部性
由于时间局部性,同一数据对象可能会被多次使用。因为缓存比第一层的存储设备更快,对后面的命中的服务回避最开始的不命中的更快。
-
利用空间局部性
块通常包含有多个对象。由于空间局部性,我们会期望后面对该快中其他对象的访问能够补偿不命中后复制该块的花费。
现代系统中到处都使用了缓存。
6.4 高速缓存存储器
早期计算机系统的存储器层次结构只有三层:CPU寄存器、DRAM主存储器和磁盘存储。
6.4.1 通用的高速缓存存储器组织结构
- 每个存储器地址有m位,形成M=2^m个不同的地址。
- 高速缓存组:S = 2^m个高速缓存组的数组
- 高速缓存行:B = 2^m字节的数据块组成
- 有效位:指明这个行是否包含有意义的信息
- 标记位:唯一地标识存储在这个高速缓存行中的块,t = m -(b+s)
一般而言,高速缓存的结构可以用元组(S,E,B,m)来描述。高速缓存的大小(或容量)C指的是所有块的大小的和。标记位和有效位不包括在内。因此,C=SEB。
6.4.2 直接映射高速缓存
直接映射高速缓存:每个组只有一行的高速缓存。
高速缓存确定一个请求是否命中,然后抽取出被请求的字的过程,分为三步:组选择、行匹配、字抽取。
- 首先,第一步 组选择:高速缓存从w的地址中间抽取出s个组索引位;
- 第二步 行匹配:当且仅当设置了有效位,而且高速缓存行中的标记与w的地址中的标记相匹配时,这一行中包含w的一个副本;
- 第三步字抽取:块偏移位提供了所需要的字的第一个字节的偏移。
根据E(每个组的高速缓存行数)高速缓存被分为不同的类。每个组只有一行的高速缓存被称为直接映射高速缓存。
1)直接映射高速缓存中的组选择
组选择就是缓存从地址A中抽取出中间的s 位,这 s 为的数值就标记了该地址所在的组。这里可以把缓存当作是一维数组,其中每个元素是一个组,而地址中的 s 位则是这些组的索引。如图中的组标记为 0001 对应组 set1。这要把地址中间的 s 为提取,就能得到该地址在缓存中对应的组。
2)直接映射高速缓存中的行匹配
在组选择之后是行匹配,选好组 i 之后,确定地址A在组 i 的哪一行。因为直接映射缓存的每一组只有一个行。所以只要看A地址中的行标记是否和缓存中的行标记位匹配。匹配则地址A中的数据在缓存中。 另一方面,如果有效位没有设置,或者标记不相匹配,那么我们就出现了缓存不命中。
3)直接映射高速缓存中的字选择
直接映射高速缓存中的行匹配和字选择。在高速缓存块中,w0表示字w的低位字节,w1是下一字节,以此类推
行匹配确定后就是字选择,一旦命中,我们就知道A就在这个块中的某个地方。最后一步确定所需要的字在块中的哪里。还是这张图,块偏移位提供了所需要的字的第一个字节的偏移。 我们把cache块看成一个字节的数组,而字节偏移是到这个数组的一个索引。
4)直接映射高速缓存中不命中时的行替换
- 如果缓存不命中,那么需要从存储器层次结构中的下一层取出被请求的块,然后将新的块存储在组索引位指示的组中的一个高速缓行中。
- 就是从下一层存储中取出数据,放入缓存的某个位置中,放入的位置就由请求地址A中的组索引确定所在缓存的组,行所以确定应该放置的行。如果组中的行都是有效缓存行了,就必须要驱逐现有的一个行。
- 替换策略:用新取出的行替换当前的行。
5)综合:运行中的直接映射高速缓存
传统的DRAM:DRAM芯片中的单元(位)被分成d个超单元,每个超单元都由w个DRAM单元组成,一个d*w的DRAM总共存储了dw位信息。超单元被组织成一个r行c列的长方形矩阵。
- 标记位和索引位连起来唯一地标识了内存中的每个块。
- 因为有8个内存块,但是只有4个高速缓存组,所以多个块会映射到同一个高速缓存组(即它们有相同的组索引)。
- 映射到同一个高速缓存组的块由标记位唯一地标识。
6)直接映射高速缓存中的冲突不命中
当程序访问大小为2的幂的数组时,直接映射高速缓存中通常会发生冲突不命中。
在这里我们举个例子看看:
1.当CPU需要读取地址为0的数据:
- 地址 0000
- 组号 0
- 有效位 0——1
- 标记位 0
分析:当CPU需要读取地址为0的数据,因为地址是(0000),所以,对应的组号是0,因为组0的开始有效位是0,所以不命中,那么高速缓存直接从内存中取出块0,放到组0中,并且置有效位为1,标记位为0(因为地址是0000)。
2.当需要读取地址为1的数据:
-地址 0001
-组号 0
-有效位 1
-标记位 0
分析:当需要读取地址为1的数据,因为地址是(0001),所以,对应的组号是0,并且组0的有效位为1,并且标记位匹配,所以命中了,那就将块中偏移为1的字节取出来。高速缓存的状态不变。
3.当CPU需要读取地址为13的数据:
-地址1101
-组号 2
-有效位 0——1
-标记位 1
分析:当需要读取地址13的数据时,因为地址是(1101),所以,对应的组号是2,组2的开始有效位是0,不命中,直接从内存中取出来,放到组2中,并且置有效位为1,标记位为1.
4.当需要读取地址为8的数据:
-地址1000
-组号 0
-有效位 1
-标记位 0——1(不匹配)
分析:当读取地址8的数据时,会发生不命中,因为地址为(1000),此时,组0的标记位为0,高速缓存行中的标记位和地址中的标记位不匹配,所以高数缓存将其他块加载到组0中,重新从新的高速缓存行块0中返回数据,置标记位为1.
6.4.3 组相联高速缓存
每个组都保存有多于一个的高速缓存行
组相联高速缓存(I<E<C/B)。在一个组相联高速缓存中,每个组包含多于一个行。这里的特例就是一个2路组相联高速缓存。
1)组相联高速缓存中的组选择
同直接映射高速缓存的组选择,组索引位标识组。
2)组相联高速缓存中的行匹配和字选择
基本思路:组中的任何一行都可以包含任何映射到这个组的内存块。所以高速缓存必须搜索组中的每一行,寻找一个有效的行,器标记和地址中的标记相匹配。如果找到了这一行,便会命中,再利用字偏移选择一个字。
3)组相联高速缓存中不命中时的行替换
- 随机选择替换策略:最简单
- 最不常使用策略:替换在过去某个时间窗口内引用次数最少的那一行
- 最近最少使用策略:替换最后一次访问时间最久远的那一行
6.4.4 全相联高速缓存
全相联高速缓存是由一个包含所有高速缓存行的组(即E=C/B)组成的。
1)全相联高速缓存中的组选择
只有一个组,默认组0,没有索引位,地址只被划分成了一个标记和一个块偏移。
2)全相联高速缓存中的行匹配和字选择
- 步骤同组相联高速缓存一样。
- 因为全相联高速缓存中需要并行的搜索续作相匹配的标记,构造一个又大又块的相联高速缓存很难,而且比较昂贵,所以全相联高速缓存只适合做小的高速缓存。
6.4.5 有关写的问题
直写,立即将w的高速缓存块协会到紧接着的低一层中
优点:简单
缺点:每次写都会引起总线流量
写回,只有当替换算法要驱逐更新过的块时,才写到紧接着的低一层中
优点:符合局部性原理,显著的减少总线流量
缺点:增加了复杂性,必须为每个高速缓存行维护一个额外的修改位
写分配---通常写回对应
加载相应的低一层中的块到高速缓存中,然后更新这个高速缓存块。
非写分配---通常直写对应
避开高速缓存,直接把这个字写在低一层中。
6.4.6 一个真实的高速缓存层次结构的解剖
存数据,也保存指令。
- 只保存指令的:i-cache
- 只保存程序数据的:d-cache
- 既保存指令又保存数据的:统一的高速缓存
6.4.7 高速缓存参数的性能影响
不命中率:不命中数量/引用数量
命中率:1-不命中率
命中时间:组选择、行确认和字选择的时间
不命中处罚:不命中需要的额外的时间
1)高度缓存大小的影响
较大的高速缓存可能会提高命中率,但也可能增加命中时间。
2)块大小的影响
较大的块能利用程序中可能存在的空间局部性,帮助提高命中率。快越大意味着高速缓存行数越少,对不命中处罚也有负面影响。
3)相联度的影响
相联度E较高,降低了高速缓存由于冲突不命中出现抖动的可能性。 但价格昂贵,运行速度慢,不命中处罚增加。
4)写策略的影响
直写高速缓存能使用独立于高速缓存的写缓冲区,用来更新存储器。高速缓存越往下层,可能使用写回而不是直写。
6.5编写高速缓存友好的代码
- 让最常见的情况运行得快
- 尽量减小每个循环内部的缓存不命中数量
- 对局部变量的反复引用是好的,因为编译器能够将它们缓存在寄存器文件中(时间局部性)
- 步长为1的引用模式是好的,因为存储器层次结构中所有层次上的缓存都是将数据存储为连续的块(空间局限性)
6.6 综合:高速缓存对程序性能的影响
6.6.1存储器山
- 存储器山是一个数字可以描述的。它是时间和空间局部性的存储器山。构造程序,是程序运行在山峰而不是山谷,利用时间局部性,使得频繁使用的字从L1取出,还要利用空间局部性,使尽可能多的字从一个L1高速缓存行中访问到。
- 我们看到,存储器山由三个坐标确定点位。底面右边的坐标是工作集大小(wording set size),按字节计数;底面左边的坐标是步长(stride),按字计数,这里可以把字理解成4字节;垂直的坐标就是读吞吐量,根据吞吐量的大小判断程序性能的优劣。
6.6.2 重新排列循环以提高空间局限性
与存储器访问总数相比,不命中率是一个较好的性能指示
6.6.3 在程序中利用局部性
- 有良好局部性的程序从快速的高速缓存存储器中访问它的大部分数据
- 局部性差的程序从DRAM主存中访问它的大部分数据
在本章最后,给大家推荐一些技术:
将你的注意力集中在内循环上,大部分计算和存储器访问都发生在这里。
通过按照数据对象存储在存储器中的顺序、以步长为1来读数据,从而使空间局部性最大。
一旦从存储器中读入了一个数据对象,就尽可能多地使用它,从而使得程序中的时间局部性最大。
教材习题
6.22
6.23
6.24
6.25-6.26
6.27-6.28
6.29-6.30
6.31-6.32
6.33
6.36-6.37
6.38-6.40
6.41-6.43
教材学习中的问题和解决过程
-
问题1:书本402页中图6-4所示,如果示例的128位DRAM被组织成一个16个超单元的线性数组,地址为0~15,为什么芯片会需要4个地址引脚而不是2个?
-
解决:查阅百度,根据CSAPP第六章-存储器的层次结构得知:DRAM组成二维阵列而不是一维线性数组的一个原因是降低芯片上地址引脚的数量。例如,16个超单元组成的阵列,二维和一维分别需要2个和4个地址引脚。二维组织的缺点是,地址必须分两步发送,增加了访问时间。(一个行地址,一个列地址)。
但还是想不出来为什么线性是4个引脚。 -
问题2:为什么要用中间的位作为组的索引,而不是组索引,标记位,和偏移量来定义地址
-
解决:在书上找到了答案,如果用高位做索引,那么一些连续的内存块就会映射到相同的高速缓存块。这样的话,顺序扫描一个数组的元素,任何时刻,高速缓存都只保存着一个块的大小的数组内容,对高速缓存的使用效率很低。
学习进度条
代码行数(新增/累积) | 博客量(新增/累积) | 学习时间(新增/累积) | 重要成长 | |
---|---|---|---|---|
目标 | 5000行 | 30篇 | 400小时 | |
第一周 | 20/20 | 1/2 | 10/15 | 第一章 |
第三周 | 130/210 | 1/2 | 21/36 | 第二章 |
第四周 | 70/ 280 | 1/4 | 10/46 | 第十章 |
第五周 | 91 / 371 | 1/6 | 23/69 | 第三章 |
第六周 | 308 / 648 | 1/8 | 31/100 | 第八、十章 |
第七周 | 2200 / 2848 | 1/10 | 25/125 | 第四章 |
第八周 | 1072 / 3492 | 1/12 | 41/166 | 第十一,十二章 |
第九周 | 508/4000 | 1/14 | 30/196 | 第六章 |
第十周 | 1377 / 3492 | 1/14 | 12/208 | 实验 实时系统 |
第十一周 | 350 / 5727 | 1/16 | 35/243 | 第九章 |
尝试一下记录「计划学习时间」和「实际学习时间」,到期末看看能不能改进自己的计划能力。这个工作学习中很重要,也很有用。 | ||||
耗时估计的公式 | ||||
:Y=X+X/N ,Y=X-X/N,训练次数多了,X、Y就接近了。 |
-
计划学习时间:30小时
-
实际学习时间:35小时
-
改进情况:
(有空多看看现代软件工程 课件
软件工程师能力自我评价表)