《深刻理解计算机系统》笔记git
存储越大寻址时间越慢、效率越低,虽然相对来讲每个数据计算机都会用到,但在某一阶段、某一个特定时间,使用到的数据范围是相对固定的。缓存
处理器须要更快速的处理速度,须要快速获得指令和数据,而这些指令和数据都是存在低级的存储中(硬盘等本地存储或网络存储),单纯拿硬盘来讲,读取时间就包括了传输时间、旋转时间、寻道时间,效率过低。为了更快速的让处理器获得数据,更好的利用处理器的性能,现代处理器演化出了分支预测的功能单元,可让处理器在未执行到某一个分支以前就经过投机先行计算(不在本次范围内)。另外,除了内部的文件寄存器,计算机将处理器和主存之间增长了多级缓存,用来存放处理器须要用到的指令和数据。所以,处理器在活动时能够经过分支预测等技术同步的将后续将会使用到的指令和数据加载到缓存中(指令高速缓存/数据高速缓存),可让整个处理器流水线的效率更高。网络
注:L0,L1,L2,L3级缓存的效率都是成百倍的下降,L4主存的效率相比L1更是天差地别。客观条件相同的状况下,存储越大寻址速度越慢。虽说从材料上面来讲也有不一样,不仅仅是大小的问题,但材料方面不在本次讨论范围内。性能
缓存是低层次存储的缓存,或者说是对低层次缓存的“凝练和融合”(L1是L2的缓存,L2是L3的缓存)。经过创建一套规则和逻辑,咱们将低层次存储中的数据根据须要读取到高层次缓存中。spa
本次说到的高速缓存的结构划分为如下几个部分(概念)设计
组 行 数据块指针
S E blockcode
一个高速缓存的大小(C)就是 S*E*B(blockSize) 其中 B S 必须是2的N次幂blog
咱们须要一套机制,将内存地址与高速缓存的索引之间创建关系,上面说的方式就是其中一种。索引
S表明了高速缓存的组数,E表明了每组中的行数,B表明每行中的数据块大小,经过这S值和B值,咱们就能够对内存地址进行掩码处理,并获得相应的组值和数据块偏移。
简单分步骤的说:
1)计算机中的信息是用二进制表示的。
2)S组都是 2的N次幂,表明他们都是经过范围的2进制位数表示的(若是S=5,那么值就多是0,1,10,11,100,101;但三位二进数还有1十、111的值,就没法用三位截取地址的方式来计算组索引了)
3)B数据块也是2的N次幂,缘由同S。
因此 s = log2(S) 就是 组索引在地址中的位数,b = log2(B)就是数据块偏移的位数。
1000 1000 1000 1000
t s b
t表明标识,设想一下,既然是缓存,那么就是将低级存储进行缓存,大小必定是比低级存储更小,因此速度更快。更小表明着较多的数据要使用较小的位置,也就是说多个地址的数据使用一个缓存位置来存数(覆盖什么规则后期再谈),那么久须要一个标识来表示这个缓存单元中的数究竟是哪一个内存的,不然读取数据的时候都不知道该读哪一个了。
t的公式是 memAddrLength - b - s。就是说,去掉组索引位和数据块偏移位,剩下的就是标识位了。
经过组和行咱们把高速缓存划分红了一个树形结构,当须要读取低级存储的时候,先将地址根据t s b的规则进行拆分,经过s找到相应的组(组数*行数*高速缓存单元的大小),再经过标识找到对应的行,而后根据块偏移把数据读出来。总的来讲就是这么简单。
实际上呢还有很多细节的问题,好比若是不命中怎么办?若是命中的时候对应的高速缓存单元还没热身怎么办(没读取数据)?若是如今内存地址对应的组都已经写满了应该替换哪个? 等等,这些计算机如今都有相应的策略,感兴趣的同窗能够去看看书。
我准备用C语言本身写一个高速缓存的机制试试,首先我没有低级存储(目前还不会硬件),低级存储是用一个指针加一部份内存空间抽象的。而高速缓存也同样,也在内存里,用一个指针加一部份内存空间抽象的。写这个的目的是为了让本身更好的理解高速缓存的原理。
实现的功能是:
1)实现高速缓存读功能,能够根据内存地址进行掩码处理获得对应的t s b值并从“高速缓存空间”中获取到高速缓存单元。
2)实现高速缓存的写功能,如今计划使用直写的方式,即直接写入到“低级存储”中不根据高速缓存的写状态进行处理。
目前进行了组件设计和活动图设计,图以下:
1)组件图:
2)交互图
3)读活动图
4)写活动图
代码后续会放到 git@code.aliyun.com:qdxiayongming/C.learn.git
望有有经验的朋友指正。