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 一般是统一的高速缓存。

6.6.2 重新排列循环以提高空间局部性