Keyboard shortcuts

Press or to navigate between chapters

Press ? to show this help

Press Esc to hide this help

快存储与大存储怎样合作

复习

  • CPU 会不断从寄存器和主存读取指令与数据
  • 寄存器很快,却不适合做得很大
  • 主存能保存更多数据,访问通常更慢

本篇讨论怎样让已经能运行的机器少等一会儿。跳过它,不影响后面连接总线与外设。

TL;DR

  • 数据会按“少而快”到“多而慢”分层存放
  • 缓存把近期可能再用的数据留在运算器附近
  • 找到叫命中,没找到叫缺失

正文

  如果所有数据都放在寄存器里,机器会快得开心,也贵得惊人;如果每次计算都去大容量设备取数,ALU 大部分时间只能干等。

  既然一种存储解决不了所有问题,就把几种存储叠起来:

寄存器        最快、最小
缓存
主存
固态硬盘等    最慢、最大

  眼前就要用的数放在上面,暂时不用的放在下面。这就是存储层次结构

为什么分层有用

  程序访问数据并不平均。刚用过的数据很可能马上再用,刚访问某个地址也常常会继续访问附近地址。前者叫时间局部性,后者叫空间局部性。

  累加一串连续数字时,机器会依次读取相邻地址;循环又会反复使用同一小段指令。只要把这些“最近、附近”的内容留在快速层,多数访问就不必跑到更慢的层级。

在书桌上留几本常用书

  缓存像书桌,主存像书架。机器读取某个地址时,先查缓存:

  • 找到了:命中,直接交出数据
  • 没找到:缺失,去主存取回,并把附近一小块数据一起放进缓存

  缓存装满后,新数据要进来,就得挑一块暂时不用的旧数据让出位置。若 CPU 修改的是缓存里的副本,还要记得把新值送回主存。具体挑哪一块、何时送回,可以以后再研究;现在先抓住缓存的工作:把可能很快再用的数据放近一点。

  缓存优化的是“取数据要等多久”。下一篇补充再看另一种性能问题:一条指令要分成许多阶段,能不能让不同指令的阶段重叠进行?不关心性能细节的读者可以直接进入总线。

思考题

  遍历连续数组,为什么通常比随机读取同样多的地址更容易命中缓存?

小结

知识点

  • 存储层次在速度、容量与成本之间折中
  • 时间局部性和空间局部性让缓存有效
  • 缓存命中、缺失、替换与写回

思考题答案(仅供参考)

  连续访问具有空间局部性。缓存取回一个地址时通常会把附近数据一起带上来,后续访问便可能直接命中;随机地址更容易反复去主存寻找。

协议

  本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

封面图

设计师 | 南国微雪