高级 #hardware#cpu#architecture

现代 CPU 架构

现代 CPU 融合了多核、超线程、乱序执行、分支预测、缓存层次等数十种技术——让单个芯片的算力达到数十亿次运算每秒

从单核到多核

2000 年代初,CPU 频率达到约 4 GHz 后遇到了功耗墙(Power Wall)——频率每提升一点,功耗和发热量大幅增加,散热跟不上了。

芯片厂商的应对方案:不再追求单核频率,而是增加核心数量

2000 年:              2020 年:
┌──────────────┐       ┌──────┬──────┐
│  Pentium 4   │       │ Core0│ Core1│
│  单核        │       ├──────┼──────┤
│  3.8 GHz     │       │ Core2│ Core3│
└──────────────┘       ├──────┼──────┤
                       │ L3 缓存(共享)│
                       └──────────────┘

多核架构

现代多核 CPU 内部:

┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐
│ Core 0   │  │ Core 1   │  │ Core 2   │  │ Core 3   │
│ ┌──────┐ │  │ ┌──────┐ │  │ ┌──────┐ │  │ ┌──────┐ │
│ │L1 I/D│ │  │ │L1 I/D│ │  │ │L1 I/D│ │  │ │L1 I/D│ │
│ ├──────┤ │  │ ├──────┤ │  │ ├──────┤ │  │ ├──────┤ │
│ │L2    │ │  │ │L2    │ │  │ │L2    │ │  │ │L2    │ │
│ └──────┘ │  │ └──────┘ │  │ └──────┘ │  │ └──────┘ │
└──────────┘  └──────────┘  └──────────┘  └──────────┘
      │              │              │              │
      └──────────────┴──────┬───────┴──────────────┘

                      ┌──────────┐
                      │  L3 缓存  │(所有核心共享)
                      └──────────┘

                      ┌──────────┐
                      │ 内存控制器│(集成在 CPU 内)
                      └──────────┘

                         RAM

每个核心:

  • 有自己的 L1/L2 缓存
  • 可以独立执行程序
  • 通过 L3 缓存和内存控制器共享数据

对称多处理(SMP)

现代操作系统中,每个核心被当成独立的 CPU 看待:

OS 视角:
CPU0 ── 进程 A, 进程 D
CPU1 ── 进程 B, 进程 E
CPU2 ── 进程 C
CPU3 ── 空闲

缓存一致性MESI 协议 保证——一个核心修改了数据,其他核心的对应缓存行自动失效。

超线程(Hyper-Threading / SMT)

Simultaneous Multithreading(SMT)——让一个物理核心同时运行两个线程。

传统单核:
时间 →  ████████████████████████████████████
        线程 A 独占总线

SMT 双线程:
时间 →  ████▓▓▓▓████▓▓▓▓████▓▓▓▓████▓▓▓▓████
        线程 A  ██ 线程 B  ██ 共享执行单元

工作原理:一个物理核心有两个逻辑处理器,它们共享执行单元(ALU、FPU),但各自有独立的寄存器组和 PC:

物理核心:
┌────────────────────────────┐
│  ┌──────┐  ┌──────┐       │
│  │ PC_A  │  │ PC_B  │       │ ← 两个逻辑 PC
│  ├──────┤  ├──────┤       │
│  │ Regs_A│  │ Regs_B│       │ ← 两套寄存器
│  ├──────┴──┴──────┤       │
│  │ 共享执行单元     │       │ ← ALU、FPU、缓存共享
│  │ ALU, FPU, L1    │       │
│  └────────────────┘       │
└────────────────────────────┘

收益:让执行单元不再”饿着”——当一个线程在等内存时,另一个线程可以用 ALU。

指标物理核数逻辑核数(开 SMT)性能提升
4 核48~30%(不是翻倍!)
8 核816~20-30%

💡 SMT 的收益取决于工作负载——数值计算提升小(因为 ALU 一直在忙),数据库/Web 服务提升大(因为经常在等内存和 I/O)。

乱序执行(Out-of-Order Execution)

早期 CPU 严格按照程序顺序执行指令。但如果下一条指令需要等上一条的结果呢?——流水线停顿。

乱序执行(OoOE) 让 CPU 在”等待”时执行后面不依赖当前结果的指令:

; 顺序执行:
LOAD R1, [mem]      ; 等内存(50 个周期)→ 流水线停顿
ADD  R2, R3, R4     ; 不依赖 R1!但只能干等

; 乱序执行:
LOAD R1, [mem]      ; 开始加载(等内存)
ADD  R2, R3, R4     ; ✅ R2 的计算不依赖 R1,先执行!
SUB  R5, R6, R7     ; ✅ 也不依赖,也先执行!
; ...(LOAD 完成了)
ADD  R8, R1, R9     ; ✅ 现在 R1 可用了,真正需要 R1 的指令才执行

乱序执行的核心结构

指令流 → ┌──────────────┐ → ┌──────────────┐ → ┌──────────────┐ → 提交结果
         │   取指解码    │    │   重排序缓冲   │    │   执行单元    │
         │(按程序顺序) │    │   ROB + RS   │    │(可乱序执行)│
         └──────────────┘    └──────────────┘    └──────────────┘
              按序进入              调度器              按序提交
                                  乱序发射              (保证精确异常)

三个关键组件:

① 重排序缓冲(Reorder Buffer, ROB):记录每条指令的状态,确保结果按序提交。

② 保留站(Reservation Station, RS):等待操作数的指令暂存区——操作数就绪后立即发射到执行单元。

③ 公共数据总线(CDB):执行结果广播给所有保留站,唤醒等待该结果的指令。

保留站中:
┌─────────────────────────────────────┐
│ 指令             操作数1    操作数2   │
│─────────────────────────────────────│
│ ADD R2, R3, R4    R3=R3     R4=R4  │← 就绪,可发射
│ SUB R5, R6, R7    R6=R6     R7=R7  │← 就绪,可发射
│ ADD R8, R1, R9    R1=等待中  R9=R9  │← 等 R1,阻塞
│ LOAD R1, [mem]    已发射     -     │← 在等内存
└─────────────────────────────────────┘
      ↑                         ↑
  当 R1 到达 CDB              唤醒 ADD R8

🔑 乱序执行的本质是:CPU 把指令调度到执行单元,不按程序顺序,而是按操作数就绪顺序。

超标量(Superscalar)

超标量 CPU 有多个执行单元,可以在一个时钟周期内发射多条指令:

非超标量(单发射):        超标量(3 发射):
每个周期最多 1 条指令      每个周期最多 3 条指令

T1: LOAD      T1: LOAD  ADD  SUB  ← 3 条并行执行!
T2: ADD       T2: STORE MUL  AND
T3: STORE     T3: ...

现代 CPU 的执行单元:

执行单元池(以 Skylake 为例):
┌────────────────────────────────────────────────┐
│  整数 ALU   │  整数 ALU   │  整数 ALU   │  整数 ALU  │ ← 4 个
├──────────────┼──────────────┼──────────────┼──────────────┤
│  浮点加法    │  浮点乘法    │  浮点除法    │  向量单元    │
├──────────────┼──────────────┼──────────────┼──────────────┤
│  内存加载    │  内存加载    │  内存存储    │  分支处理    │
└──────────────┴──────────────┴──────────────┴──────────────┘

💡 现代桌面 CPU 每周期最多可以发射 4-6 条指令(如果指令之间没有依赖关系)。

分支预测器

指令流水线 中提到分支预测。现代分支预测器已经非常复杂:

一级预测(简单历史):
BEQ 上次跳了吗?→ 预测这次也跳/不跳

二级预测(全局历史):
记录最近 N 次分支的结果 → 预测下一跳

三级预测(混合预测器 + AI 风格):
- TAGE 预测器:使用多张历史表,按历史长度匹配
- 循环预测器:专门预测固定次数的循环
- 统计预测器:用神经网络风格的权重

现代分支预测器的准确率:> 97%(服务器负载下)到 > 99.9%(科学计算)。

推测执行(Speculative Execution)

CPU 不仅仅预测分支——它还会推测执行预测方向后的代码:

BEQ R1, R2, else   ; 预测不跳转
ADD R3, R4, R5     ; ← CPU 推测执行这条
LOAD R6, [R7]      ; ← 甚至继续往下推测执行
                   ; 如果预测正确:这些指令的结果直接可用
                   ; 如果预测错误:丢弃推测结果,回滚

推测执行是乱序执行的延伸——但也是安全漏洞的来源(如 Spectre、Meltdown 漏洞,推测执行访问了不该访问的内存,留下了可测量的痕迹)。

现代 CPU 的完整执行流程

① 取指(Fetch):
   从 L1 指令缓存读取 16-32 字节指令
   预解码(标记指令边界)

② 解码(Decode):
   x86:解码为微操作(μops)
   RISC:直接解码
   每周期解码 4-6 条指令

③ 重命名(Register Renaming):
   把架构寄存器映射到物理寄存器
   消除"写后写"(WAW)和"写后读"(WAR)依赖

④ 调度(Schedule):
   放到保留站 → 操作数就绪 → 发射到执行单元

⑤ 执行(Execute):
   多个执行单元并行执行
   结果通过 CDB 广播

⑥ 提交(Commit):
   按程序顺序提交结果到 ROB
   保证精确异常——异常发生时可以正确回滚

⑦ 写回(WriteBack):
   结果写入寄存器文件和缓存

功耗与散热

现代 CPU 面临的核心矛盾:

性能 ∝ 频率² × 核心数
功耗 ∝ 频率³ × 核心数

这意味着频率提升 10%,功耗增加约 33%。这就是为什么 CPU 频率停滞在 4-5 GHz 附近。

省电技术

技术做法节电效果
动态频率调整负载低时降频30-50%
休眠状态(C-states)空闲核心进入休眠接近零功耗
时钟门控关闭不用单元的时钟减少动态功耗
电源门控关闭不用单元的电源减少漏电功耗
DVFS(动态调压调频)降低电压配合降频功耗∝V²

大小核架构(big.LITTLE / Hybrid)

现代 CPU 混合使用高性能大核和省电小核:

Intel Core i7-12700(混合架构):
┌──────────────┐  ┌──────────────┐
│  P-core × 6  │  │  E-core × 4  │
│  高性能核心   │  │  能效核心    │
│  5.0 GHz     │  │  3.6 GHz     │
│  大 L2 缓存  │  │  小 L2 缓存  │
└──────────────┘  └──────────────┘

OS 调度器把前台任务放 P-core,后台任务放 E-core——既保证了响应速度,又延长了续航。

从数字到感觉

// 现代 CPU 一秒钟可以做的事情:
3 GHz × 4 核 × 1.5 IPC ≈ 180 亿条指令/

// 如果你每秒写一条指令:
//   ≈ 570 年才能赶上 CPU 一秒的工作量!

小结

现代 CPU 是几十项技术的融合:

技术解决的问题效果
多核功耗墙限制了单核频率通过并行提升吞吐量
超线程(SMT)单个核心的执行单元可能空闲利用率提升 20-30%
乱序执行指令等待数据时流水线停顿隐藏内存延迟
超标量每周期只能执行一条指令每周期执行 4-6 条
分支预测分支导致流水线冲刷准确率 > 97%
推测执行等待分支结果时浪费周期利用等待时间提前执行
大小核架构性能和功耗的矛盾兼顾爆发性能和日常省电

为什么这很重要? 现代 CPU 不是一个”每周期执行一条指令的简单机器”——它是一个极其复杂的并行引擎,同时处理几十条指令,预测未来、推测执行、动态调度。理解这些技术,你才算真正理解了你每天都在使用的”CPU”到底是什么。

至此,硬件板块全部完成! 你已经走完了从数字电路→逻辑门→CPU 核心→存储系统→现代处理器架构的完整旅程。接下来,你将从硬件视角切换到软件视角——从我们之前完成的汇编语言进入操作系统(02-os) 的世界。