大家好啊,我是 jianpeng。今天和大家聊一下 CPU 与 GPU 的架构区别。

读深度学习的硬件资料时,我们会同时遇到 CPU Core、CUDA Core、Tensor Core、SM、缓存和显存。它们处在不同层级,光看“核心数量”,很难解释一次矩阵乘法为什么快,或者为什么计算单元还在等数据。

这次我选 AMD Ryzen 9 7950X 和 NVIDIA H100 SXM,沿着封装、执行组织、存储层次这条线往里看。前者是桌面多芯粒 CPU,后者是数据中心 GPU;两者的产品定位不同,这里比较的是结构及其工作方式。

先把一个常见误解说清楚:CPU 也能训练模型和做推理。PyTorch 官方入门教程就保留了 CPU 执行路径,Google TPU 等专用加速器也支持训练与推理。GPU 在深度学习中常见,关键在于它怎样组织大量运算,以及怎样为这些运算供给数据。

1. 7950X 的三颗裸片,划出了怎样的缓存边界?

先看封装层。7950X 的散热顶盖下有两颗计算芯粒 CCD,以及一颗输入输出芯粒 IOD。下面是文章中 Three.js 模型的封装拆分截图,其中的厚度与拆分间距均为示意。

先认清两个名字:CCD(Core Complex Die) 是承载 CPU 核心与缓存的计算芯粒;IOD(I/O Die) 是输入输出芯粒,I/O 即 Input/Output,负责连接计算芯粒、内存和外部接口。两者都是封装内的硅片;一颗 CCD 里面还包含多个 CPU 核心。

Ryzen 9 7950X 封装拆分模型:散热顶盖、两颗 CCD、一颗 IOD 与封装基板

两颗 CCD 与 IOD 安装在同一块基板上。每颗 CCD 有 8 个 Zen 4 核心,合计 16 核;每核支持两个硬件线程,因此产品规格为 16 核、32 线程。两个硬件线程共享部分执行资源。

图中 CCD、IOD 表面叠加了 Fritzchens Fritz 对 Ryzen 5 7600 Raphael 样本拍摄的多晶硅层显微图与短波红外影像,用于展示同代硅片内部纹理。这些颜色来自制备样本的成像,开盖后肉眼看到的表面并非如此。7950X 的双 CCD 配置与启用核心数量依据 AMD 规格。

缓存要按作用范围分开读:

L1、L2、L3 分别是 Level 1、Level 2、Level 3 cache,即一级、二级、三级缓存。缓存保存数据或指令的副本,减少访问外部内存的等待。层级数字描述它在存储体系中的位置;在这款 CPU 中,L2 属于各个核心,L3 在同一颗 CCD 内共享。

部件或层级7950X 的组织与程序执行的关系
CPU 核心每颗 CCD 8 核,共 16 核各核心执行指令,支持两个硬件线程
L2 缓存每核 1 MB,合计 16 MB每个核心自己的缓存层级
L3 缓存每颗 CCD 32 MB,合计 64 MB在同一颗 CCD 的 8 个核心之间共享
IOD一颗输入输出芯粒连接 DDR5 内存、PCIe 等接口,并包含显示和媒体等功能

表中的 DDR5 是第五代 DDR 内存标准。DDR 即 Double Data Rate(双倍数据速率),数据可在时钟的上升沿和下降沿传输;5 表示标准的代际。它是这台电脑主内存所用的技术,不是片上的 L3 缓存。PCIe(Peripheral Component Interconnect Express) 则是连接显卡、固态硬盘等设备的高速接口。

再看 AMD 公开的 Zen 4 CCD 裸片分区图。观察重点是 Core、L2 与 L3 的相对位置。

AMD Zen 4 CCD 裸片分区图:两侧各四组 Core 与 L2,中央为 32 MB L3

图中两侧各有四组 Core + L2,中央是共享的 32 MB L3。这些区域做在同一颗硅片上。7950X 的另一颗 CCD 也有自己的一组核心和 L3,所以规格中的 64 MB L3 分布在两颗 CCD 内;核心访问本 CCD 与另一颗 CCD 的数据,经过的路径不同。

本文使用的普通 7950X 没有 X3D 型号额外堆叠的缓存芯片。把封装里的三颗裸片,与裸片内部的缓存区域分清,后面的架构图就容易读了。

2. 一个 Zen 4 核心,怎样把指令送到执行单元?

CPU 不断处理指令之间的依赖:有的计算必须等前一个结果,有的内存地址要先算出来,有的代码要根据条件选择下一条路径。分支预测、重命名、乱序调度等电路,参与处理这些问题。

下面这张 AMD 官方核心功能图适合沿箭头阅读:先找前端的取指、译码和 Op Cache,再看 Dispatch 之后的整数与浮点路径。

AMD Zen 4 核心功能图:前端、队列、分派、整数与浮点执行路径及缓存连接

前端可以从指令缓存取出指令并译码,也可以从 Op Cache 取得已经译码的操作。它们进入队列,随后由 Dispatch 分派。重命名与调度电路跟踪操作数和依赖,把已经具备执行条件的操作送往相应单元。

整数路径里既有算术逻辑单元,也有参与生成访存地址的 AGU;浮点路径里有浮点与 SIMD 寄存器及执行单元。Load/Store 单元处理读写,连接数据缓存。寄存器、队列、运算单元和缓存各有职责,图中的箭头描述的是功能通路,框的大小并不对应硅片面积。

这套组织适合处理变化较多的控制流程。例如解析一个请求,沿一串相互依赖的地址读取数据,再根据结果决定下一步,后续工作就很难预先全部拆开。

CPU 同时也在提高吞吐:多核可以执行多个任务,向量指令可以同时处理多个数据元素,乱序执行则寻找指令之间可利用的并行。Zen 4 支持 AVX-512,CPU 本身具备向量计算能力。

3. H100 把大量线程组织成什么样?

H100 SXM 的封装结构换了一种思路:中央是一颗 GH100 GPU 裸片,周围是 HBM(High Bandwidth Memory,高带宽内存)所在区域,GPU 与 HBM 通过中介层连接。HBM 在这里承担显存的工作,用来存放权重、输入和中间结果,HBM3 表示第三代 HBM。先从下面的模型截图看清它们在封装中的位置。

H100 SXM 封装拆分模型:中央 GH100、周边内存区域、中介层与封装基板

GPU 与 HBM 并排放置;HBM 内部的 DRAM 芯片才是竖向堆叠。图中保留产品外观的六个周边位置,H100 SXM 80 GB 规格计入五个有效 HBM3 堆栈。SM、L2 缓存和控制逻辑都集成在中央的 GH100 裸片内。模型的厚度和层间距离是示意参数。

中央裸片表面覆盖的是 HiEQ 发布的 GH100 标注图,其中的精确区域划分属于作者分析。下文解释 SM 功能时,采用的是 NVIDIA 官方架构图。

SM(Streaming Multiprocessor,流式多处理器) 是 NVIDIA GPU 内部组织线程和运算的功能模块。一个 SM 配有指令调度、寄存器、共享内存/L1,以及多种运算单元;多个 SM 再协作完成 GPU 的工作。它不是另封装的一颗芯片。CUDA Core 与完整的 CPU Core 处在不同的组织层级,数量不能直接相除得出速度比。

NVIDIA 的完整 GH100 设计包含 144 个 SM;H100 SXM 产品启用 132 个 SM,每个 SM 有 4 个第四代 Tensor Core,合计 528 个。完整设计与产品启用配置要分别读取。

在单个 SM 的官方功能图中,可以重点看四个处理分区:调度与寄存器资源怎样连接不同的执行单元,以及它们下方的共享内存/L1。

NVIDIA GH100 SM 官方功能图:四个处理分区、调度与寄存器、算术单元及共享内存和 L1

四个分区各有 Warp 调度器、指令派发单元与寄存器资源,连接 FP32、FP64、INT32 和 Tensor Core 等执行单元。LD/ST 处理加载和存储,SFU 处理特定函数运算。Tensor Core 执行支持格式与形状的矩阵乘加,其他单元继续处理索引、分支和其他算术工作。

线程要用的操作数保存在寄存器中;同一线程块中的线程可以通过共享内存交换、复用数据;L1 缓存由硬件管理。共享内存和 L1 使用组合资源,但程序使用两者的方式不同。

当一批线程等待数据时,调度器可以选择其他已就绪的线程工作,用并发来减少执行资源空闲的时间。要做到这一点,程序需要提供足够多的可并行工作。数据规模小、同一 Warp 内线程走向不同分支,或者数据搬运频繁,都可能影响利用率。

4. 一次矩阵乘法,怎样用到这些结构?

我们用一个教学计算,把上面的执行单元和存储层次串起来。设输入矩阵 X 的形状为 64 × 4096,权重矩阵 W 为 4096 × 4096,计算 Y = X × W,输出形状就是 64 × 4096。

按一次乘加计两次浮点操作,计算量的常用估算为:

X: 64 × 4096
W: 4096 × 4096
Y: 64 × 4096

FLOPs ≈ 2 × 64 × 4096 × 4096
      = 2,147,483,648
      ≈ 21.5 亿次浮点操作

这个数字描述运算量。要花多长时间,还取决于执行效率和数据搬运。

Y 的许多元素可以并行计算,同一个权重块也能被多个输入复用。GPU 内核通常将矩阵切成小块,让线程协作处理,再把已经搬入寄存器、共享内存的数据多用几次。在适合的格式和布局下,矩阵指令可以将小块运算交给 Tensor Core。

如果每次乘加都重新从显存取数,计算单元会花大量时间等待。H100 的 HBM、片上 L2、SM 中的 L1、共享内存和寄存器构成了数据供给的不同层级。实际走哪条访问路径,由指令和缓存策略决定。

这也解释了为什么增加批量有时能提高吞吐:一次加载的权重可以服务更多输入。不过,批量变大也会增加内存需求,还可能改变请求的等待时间。并行度、数据复用和响应时间之间存在具体取舍。

CPU 和 GPU 都在利用并行与缓存,但常用的组织方式有所不同:

观察点通用 CPU 的典型组织GPU 的典型组织
执行并行多核、向量指令、指令级并行多个 SM 调度大量线程,协作处理数据块
处理等待缓存、预测、乱序执行缓存和数据复用,加上并发线程掩盖等待
本文的外部内存7950X 经 IOD 连接主板上的 DDR5H100 SXM 的 HBM3 与 GPU 位于同一封装
常见 AI 工作也能训练和推理,并常承担数据准备与调度大规模张量计算、训练和高吞吐推理

GPU 还需要软件把工作组织成合适的形状。CUDA、cuBLAS、cuDNN 与深度学习框架为常见算子提供了经过优化的实现;多卡训练还涉及设备间通信。一个峰值 TFLOPS 数字,只覆盖了这条执行链中的一部分。

FP16、BF16、FP8 等格式也是类似的道理。降低位宽可以减少存储和搬运,受支持的硬件可能提供更高吞吐;但模型、算子和训练策略必须适配,并验证精度变化对模型质量的影响。

5. 训练和推理,为什么会卡在不同地方?

同一个模型,训练与推理保存的数据和执行的计算并不相同。

训练除了前向计算,还要进行反向传播并更新参数。除权重外,通常要保留反向传播所需的中间状态、梯度和优化器状态。因此,训练的内存需求会随优化器、精度、激活重计算和并行策略变化。仅仅容纳权重,还不足以说明训练所需的内存已经够用。

推理使用已有权重产生结果,通常不进行反向传播和参数更新,但需要运行时工作区。对于自回归大语言模型,还要保存历史注意力的键和值,也就是 KV cache,其容量会随上下文和并发等条件增长。

大语言模型推理内部,还可以继续区分两个阶段:

阶段主要工作常见的性能特点
预填充(prefill)处理输入提示中的多个 token容易形成较大的矩阵运算
解码(decode)逐步产生后续 token单条序列的后续步骤依赖前一步,小批量时可能更受内存带宽影响

小批量解码时,反复读取权重和 KV cache 可能比算术执行更限制速度;批量、上下文长度和模型结构改变后,瓶颈也会移动。GPU 有很高的矩阵峰值算力,并不意味着每个生成步骤都能用满它。

读到这里,再看“训练吞吐”“首 token 延迟”“后续 token 速度”这几个指标,就能把它们放回不同的执行阶段:它们可能分别受计算、访存、通信或数据依赖影响。理解这些差别,才知道架构图里的哪一部分正在决定程序的表现。

引用链接

更多推荐