处理器体系结构:从指令流水线到多核芯片 / Processor Architecture from Instruction Pipelines to Multicore Chips
📅 创建时间:2026-07-20 🏷️ 标签:#CPU #体系结构 #流水线 #乱序执行 #多核 📚 前置知识:[[01-parallel-foundations]] 📚 相关知识:[[/02-systems-and-performance/02-computer-architecture-and-hardware/01-computer-architecture-basics]]
1. 一条指令怎样执行
处理器执行指令通常可以抽象为:
取指 → 译码 → 读取操作数 → 执行 → 访存 → 写回如果每条指令必须完整结束后才能开始下一条,大量硬件会处于空闲。因此处理器使用流水线,让多条指令处于不同阶段。
周期 1:指令 A 取指
周期 2:指令 A 译码,指令 B 取指
周期 3:指令 A 执行,指令 B 译码,指令 C 取指流水线提高吞吐,但不会等比例降低单条指令的延迟。
2. 指令级并行
现代 CPU 会在单个核心内部寻找互不依赖的指令并行执行。
超标量
一个周期可以发射多条指令到不同执行单元,例如整数单元、浮点单元和加载存储单元。
乱序执行
a = load(slow_address); // Cache Miss
b = x + y; // 与 a 无关
c = m * n; // 与 a 无关CPU 不必等待第一条加载结束,可以先执行后两条指令,最后按程序顺序提交结果。
分支预测
遇到 if 时,CPU 会预测执行路径并提前工作。预测错误后,错误路径的流水线结果必须丢弃。
这也是规则循环通常比大量不可预测分支更容易获得高性能的原因。
3. 从提高频率转向增加核心
早期处理器主要依赖提高时钟频率,但功耗近似受到频率和电压的共同影响:
动态功耗 ≈ 电容 × 电压² × 频率频率继续增长带来严重发热和能耗问题,行业转向:
- 多核 CPU
- 更宽的 SIMD
- 专用加速器
- 大规模 GPU
这意味着软件必须显式或隐式地利用并行,才能继续获得性能增长。
4. 核心、硬件线程与逻辑处理器
物理核心
拥有独立的执行资源,可以真正与其他核心并行。
同时多线程 SMT
一个物理核心维护多个硬件线程上下文。当一个线程等待数据时,另一个线程使用部分空闲执行资源。
8 核 16 线程 ≠ 16 个完整核心SMT 的收益依赖工作负载。两个都占满相同执行单元的线程可能互相竞争。
5. CPU、GPU 与专用加速器
| 特性 | CPU | GPU | NPU/TPU |
|---|---|---|---|
| 核心数量 | 少量复杂核心 | 大量较简单执行单元 | 大量矩阵/张量单元 |
| 控制能力 | 强 | 中等 | 较弱或领域限定 |
| 单线程延迟 | 低 | 较高 | 依任务而定 |
| 吞吐能力 | 中等 | 高 | 特定算子极高 |
| 适合任务 | 操作系统、业务逻辑、复杂分支 | 图形、矩阵、规则数据并行 | AI 推理与训练 |
CPU 花费大量晶体管降低单线程延迟,GPU 把更多面积用于执行单元以提升总吞吐。
6. 并行层次
一台现代计算机中同时存在多层并行:
多节点并行
└─ 单节点多处理器/多 GPU
└─ 多核并行
└─ SMT 硬件线程
└─ SIMD 向量并行
└─ 流水线与乱序执行高性能程序通常不是只选择其中一种,而是组合多层并行。例如 MPI 跨节点、OpenMP 跨 CPU 核、SIMD 处理核心内部的数据。
7. 峰值性能不等于应用性能
理论浮点峰值可以粗略表示为:
峰值 FLOPS = 核心数 × 频率 × 每周期浮点操作数但应用还受到以下因素限制:
- 数据是否在 Cache 中
- 指令是否能够并行发射
- 分支预测是否准确
- SIMD 通道是否充分利用
- 内存带宽是否足够
- 多核之间是否频繁同步
因此硬件参数是上限,不是性能承诺。
8. 前端供给
CPU 前端负责取指、预测、译码和微操作供给。
前端受限来源:
- I-Cache Miss;
- iTLB Miss;
- 分支预测错误;
- 代码体积;
- 译码宽度;
- 微操作 Cache;
- 间接跳转;
- 频繁虚调用。
循环展开减少控制指令,也会扩大代码。 是否有效需要测量。
9. 乱序执行
处理器在架构语义允许范围内重排独立微操作。
Register Renaming 消除部分名字依赖。 Reservation Station 等待真实输入就绪。
最终按架构顺序退休,保证可观察状态。
长依赖链无法通过增加执行单元加速。
10. 执行端口
整数、浮点、向量、Load 和 Store 使用不同端口与单元。
热点可能受:
- 端口吞吐;
- 指令延迟;
- 数据依赖;
- Load/Store;
- 地址生成;
- 除法和特殊函数;
- Shuffle;
- 转换。
汇编与微架构工具用于确认实际指令组合。
11. 分支预测
预测器使用历史和地址模式猜测分支方向与目标。
预测错误需要清空错误路径工作。
难预测分支包括:
- 随机数据条件;
- 间接跳转;
- 多态分派;
- 数据依赖状态机;
- 低重复模式。
排序、分区、查表和 Mask 可能改善,但会增加其他成本。
12. SIMD
SIMD 在一条指令内处理多个 Lane。
向量化需要:
- 独立迭代;
- 连续或可处理访问;
- 明确别名;
- 适合的数据类型;
- 可向量化函数;
- 可控分支;
- 足够循环长度。
编译器报告和汇编用于确认。
13. Cache 一致性
多个核心缓存共享内存时需要一致性协议。
共享写会产生失效和所有权转移。
False Sharing 中,线程修改不同字段,却因同一 Cache Line 互相干扰。
线程局部状态和分片通常比高频全局原子更容易扩展。
14. SMT
SMT 让一个物理核心运行多个硬件线程。
它可以利用一个线程等待时的空闲资源。
线程之间也会竞争:
- 前端;
- 执行端口;
- Cache;
- TLB;
- 带宽;
- 功耗。
CPU 密集任务需要比较物理核心与逻辑线程配置。
15. NUMA
多插槽系统具有本地和远端内存。
socket 0 -> local memory 0
socket 1 -> local memory 1首次触碰、线程亲和性和数据分片决定访问路径。
绑核不是默认优化。 只有拓扑稳定且测量证明时才固定。
16. 频率与功耗
频率受负载、核心数、向量指令、温度和电源策略影响。
短 Benchmark 的 Boost 不能代表长时间稳定频率。
记录:
- 频率;
- 温度;
- 功耗;
- 活跃核心;
- 电源计划;
- 节流事件。
17. 虚拟化
虚拟机和容器可能限制:
- 可见 CPU;
- PMU;
- 频率;
- NUMA;
- 调度配额;
- Huge Page;
- 设备直通。
性能报告必须记录运行环境。
18. 分析工具
工具组合:
- WPR/WPA:Windows 系统时间线和线程状态;
- VTune Hotspots:函数与调用路径;
- VTune Microarchitecture:流水线分类;
- VTune Memory Access:Cache/NUMA/带宽;
- Linux Perf:采样和硬件事件;
- 编译器报告:向量化与内联;
- 汇编工具:指令与端口。
19. 实验
建议实验:
- 可预测与随机分支;
- 单链与多独立累加器;
- 标量与 SIMD;
- 不同工作集;
- False Sharing;
- SMT 开关;
- NUMA 首次触碰;
- 线程亲和性;
- 长短运行频率;
- Debug/Release。
20. 完成标准
应能回答:
- 前端是否供给不足;
- 分支是否浪费工作;
- 依赖链是否限制;
- 指令是否向量化;
- Cache 与带宽是否受限;
- SMT 是否有益;
- NUMA 是否远端;
- 频率是否稳定;
- 哪个工具验证假设。
最终结论必须绑定目标处理器、编译器、输入和构建参数。 跨微架构迁移时重新采集,不复用旧计数器阈值。 一次完整实验还应保存原始样本,便于复核。
核心总结
- 单核内部已经包含流水线、乱序执行和 SIMD 等并行机制。
- 多核是功耗墙之后性能增长的主要方向。
- CPU 追求低延迟和通用性,GPU 追求高吞吐。
- 真正的并行程序往往同时利用多个体系结构层次。
下一篇:[[03-cpu-parallelism]]