首页 / 知识库 / 进大厂必备计算机基础 / 计算机组成原理

06 - 为什么要有寄存器和多级缓存

上一章留了个问题:CPU 快、内存慢,CPU 每次取数据都得干等内存,太亏了。这一章讲清楚硬件是怎么解决这个「快慢不匹配」的——答案又是那个熟悉的思想:分层 + 缓存

问题有多严重

打个直观的比方:如果 CPU 做一次计算只要「1 秒」,那么它去内存取一次数据,大约要等「几分钟」。也就是说,CPU 算得再快,也常常在干等内存送数据。这就像一个手速极快的大厨,食材却要从很远的仓库一趟趟搬,大部分时间都浪费在等食材上。

解决思路很自然:在 CPU 和内存之间,塞几层「离 CPU 更近、更快」的小仓库,把常用的数据提前放进去。 这就是存储金字塔在硬件里的落地。

硬件里的存储层级

从离 CPU 最近(最快最小)到最远(最慢最大):

  ┌──────────────┐  最快、最小、最贵
  │   寄存器      │  在 CPU 核心里,几十个,装正在算的数
  ├──────────────┤
  │  L1 缓存      │  每个核私有,很小很快
  │  L2 缓存      │  稍大稍慢
  │  L3 缓存      │  多核共享,更大更慢
  ├──────────────┤
  │   内存 (RAM)  │  大很多,但慢很多
  └──────────────┘  最慢、最大、最便宜

寄存器(Register)

CPU 内部最快的存储,就在运算单元旁边,但数量极少(几十个)、每个只能装一点点。CPU 正在计算的那几个数,就临时放在寄存器里,存取几乎不花时间。

相当于大厨手边案板上正在切的那几样菜——伸手就够到。

CPU 缓存(Cache,分 L1/L2/L3)

寄存器太少了,装不下稍多的数据。于是在寄存器和内存之间,加了几层缓存,用的是比内存更快的材料。

  • L1:最小最快,每个 CPU 核独享。
  • L2:大一点、慢一点。
  • L3:更大、更慢,通常多个核共享。

相当于厨房里离灶台近的小料理台——比跑仓库快多了,放着这道菜大概率会用到的食材。

CPU 取数据的流程

CPU 要一个数据时,从近到远一层层问:

寄存器有吗? → 有,直接用(最快)
      │没有

L1 有吗? → 有,拿来(很快)
      │没有

L2 / L3 有吗? → 有,拿来(较快)
      │没有

去内存拿(慢),顺便复制一份到缓存里,赌待会儿还用
  • 在缓存里找到了,叫命中(Cache Hit),飞快。
  • 没找到得去下一层,叫未命中(Cache Miss),慢,但拿回来时会顺手缓存一份。

为什么缓存能生效:局部性

缓存这套「赌你待会还用」的策略之所以有效,靠的是程序访问数据的局部性规律(操作系统篇第 10 章讲过,这里再强调,因为它太重要了):

  • 时间局部性:刚用过的数据,很可能马上又用(比如循环里反复用的变量)。
  • 空间局部性:用了某个数据,它旁边的数据也很可能马上用(比如挨个遍历数组)。

正因如此,CPU 从内存取数据时,往往不是只取你要的那一个,而是把它连同旁边一小块(叫「缓存行」)一起搬进缓存,赌你接下来会用到旁边的。

这就是为什么「顺序访问数组」比「东一下西一下地乱访问」快得多——顺序访问对缓存友好,命中率高。写高性能代码时,这是个重要直觉。

小结

  • CPU 远快于内存,直接取内存会让 CPU 大量时间干等,所以在中间加了几层更快的存储。
  • 硬件存储层级(快→慢):寄存器 → L1/L2/L3 缓存 → 内存,越近越快越小越贵。
  • 寄存器装正在算的数(手边案板);缓存装大概率要用的数据(近处料理台)。
  • CPU 取数据逐层查找,找到叫命中(快),没找到叫未命中(慢,但会顺手缓存)。
  • 缓存靠局部性(时间/空间)生效,还会连带旁边一整块一起缓存——所以顺序访问更快。

下一章 → 07 - 时钟、指令、流水线:CPU 为什么越来越快 | 回到 README 目录