6.1 存储技术
6.1.1 随机访问存储器
- RAM
- SRAM
- DRAM
- ROM
6.1.2 磁盘存储
6.1.3 固态硬盘
大约十万次写会导致块损坏。
6.2 局部性
6.4 高速缓冲存储器
// todo: 添加截图
高速缓存确定一个请求是否命中,然后抽出被请求字的过程分为三步:
- 组选择
- 行匹配
- 字抽取
6.4.2 直接映射高速缓存
每组只有一行(E=1)。
// todo: 添加截图
6.4.3 组相连高速缓存
1<E<C/B
组选择
和直接映射高速缓存相同。
行匹配和字选择
每组的任何一行都可以包含任何映射到这个组的内存块。
所以高速缓存必须搜索组中的每一行,寻找一个有效行,其标记与地址中的标记相匹配。
行替换
行替换算法:
LFU: Least frequently used. 替换过去某个时间窗口引用次数最少的一行。 LRU: Least recently used. 替换最后一次访问时间最久远的一行。
6.4.4 全相连高速缓存
//todo: 插图
E=CB,一个组包含所有行。
组选择
只有一个组,没有组索引。
行匹配和字选择
构建一个又大又快的相连高速缓存很困难,而且很昂贵。因此全相连高速缓存只适合做小的高速缓存,例如虚拟内存中的 TLB。
6.4.5 有关写的问题
写命中
假设我们要写一个已经缓存了的字 w(写命中)。
首先都会先更新高速缓存中的字 w,接着更新低一级的内存中的数据,有两种方式:
- write-through 直写。立即将 w 的高速缓存块写回到低一层中。
- wirte-back 写回。尽可能地推迟更新,只有当替换算法要驱逐这个更新过的块时,才写到低一层去。
写回可以显著减少总线流量,但增加了复杂性,需要额外维护一个 dirty bit,表示这个高速缓存快块是否修改过。
写不命中
- write-allocate 写分配。加载相应低一层的块到高速缓存中,然后更新这个缓存块。
- non-write-allocate 非写分配。避开高速缓存,直接写到底一层。
write-through 一般对应 non-write-allocate。 write-back 一般对应 write-allocate。
对于试图编写高速缓存比较友好的程序的程序猿来说,建议在心中采用一个使用写回和写分配的高速缓存模型。
6.4.6 一个真实的高速缓存层次结构的解剖
只保存指令的高速缓存称为 i-cache。
只保存程序数据的高速缓存称为 d-cache。
既保存指令又保存数据的高速缓存称为统一的高速缓存。
//todo: 插图
L1 cache 由 icache 和 dcache 组成,其他 L2,L3 cache 一般是统一的高速缓存。