GPU 很忙,为什么任务仍然慢?

把计算、访存、传输与等待分开,用时间线和内存账解释瓶颈。

第 02 单元 · 约 70 分钟(含练习) · 产出:一份瓶颈假设与反证记录

从哪里接上:第 01 课的观察边界

先问:这个“忙”究竟测到了什么?

你接手一个模型服务,监控显示 GPU 利用率接近 95%,用户还是在等。最容易下的结论是“卡不够,扩容”。但这个百分比并没有告诉你:算子在做矩阵乘法,还是在等显存中的数据?CPU 是否在准备下一批输入?一个请求是否先在队列里耗掉了两秒?先画执行路径,再决定该换哪一个变量。

GPU 是由很多执行单元组成的设备,适合对大量数据执行相似运算。CPU 通常负责控制流程、数据准备和提交工作;设备上的 kernel 是一段真正执行计算的程序。输入可能从存储进入主机内存,再通过主机到设备的传输到达显存。kernel 从显存读取数据、计算、写回结果。不同内存层与互联有不同的带宽和时延。设备有工作在执行,不等于每个执行单元都在高效计算。

这一课不要求你编写 CUDA。你要学会沿这条路径提出可以检验的解释:是数据晚到了,是传输串在关键路径上,是访存量太大,还是很多小 kernel 的启动间隙占了时间?第 01 课的端到端时间是问题的入口,下面的设备时间才解释其中一段。

一条时间线,胜过几个平均百分比

先看一个刻意串行的教学例。CPU 准备 5ms,传输 5ms,GPU 执行 100ms,响应整理 5ms,共 115ms。这里没有重叠,所以可以相加;在真实异步流水线里,不能直接把各阶段总时间相加作为端到端时延,要找关键路径。

串行教学时间线:设备执行占大多数时间,但不区分算术与访存等待 从0到115毫秒:CPU准备5,主机设备传输5,设备执行100,响应整理5。第二个例子为CPU准备80,传输10,设备执行10,响应整理5,共105毫秒,说明相近时延可有不同瓶颈。 A:GPU 段长,但要继续看 kernel 内部 CPU 5ms · 传输 5ms设备执行 100ms返回 5ms B:GPU 在等输入,增加设备不一定有帮助 CPU / 数据准备 80ms传输 10ms · GPU 10ms · 返回 5ms;总计 105ms,两个例子使用相同时间比例。
图 02.1 · 两份虚构的串行 trace。条带回答“时间花在哪里”,不冒充实际 Profiler 结果;实际流水线还要检查阶段重叠。

例 B 的下一步应是检查解码、存储读取、预处理或数据队列。你可以预取输入来测试假设,但预取增加主机内存占用,也可能把瓶颈移到存储。例 A 则要进入 kernel:同样 100ms 的设备段,可以主要受计算能力限制,也可以主要受显存带宽限制。只看到长条,仍不能宣布“计算瓶颈”。

用计算量和访存量,给解释加一道约束

把一个 kernel 的计算量记作 F(FLOPs),在所研究的存储层实际搬运的字节记作 D。算术强度 I=F/D,单位是 FLOP/byte。如果同精度下的计算峰值是 P,带宽是 B,理想时间下界为 max(F/P, D/B)。同一思想写成绩效上界就是 min(P, B×I),常被称为 roofline 模型。

注意两个词:同精度和理想下界。不能把 FP32 的任务拿去除以另一种精度的宣传峰值;D 也不是简单读取模型文件的大小,而是相关存储层的流量。kernel 启动、同步、分支、占用率不足与通信都可能使实际时间更长。这个估算帮助排除不合理解释,不是性能预测器。

把例 A 拆开

虚构设备的峰值为 100 TFLOP/s,显存带宽为 1 TB/s,即 1,000 GB/s。任务执行 2×10¹² FLOPs,搬运 100 GB:

  1. 算术强度:2×10¹² ÷ 10¹¹ = 20 FLOP/byte。
  2. 计算时间下界:2 ÷ 100 = 0.02s,即 20ms。
  3. 访存时间下界:100 ÷ 1,000 = 0.1s,即 100ms。
  4. 理想下界取较大者,得到 100ms。此模型中先降低流量比提高峰值算力更有希望。

现在把流量减少到 10 GB,计算量保持不变。访存下界变为 10ms,计算下界仍为 20ms,总下界变为 20ms。再把流量减到 5 GB,下界仍是 20ms:瓶颈已经转移。真实优化后如果实际仍是 60ms,你应寻找这个模型未包含的限制,而不是把观测强行改成 20ms。

计算实验

先预测,再改一个变量

默认值来自上面的虚构算例。先写下将流量改为 10 GB 的预测,再计算;其余三个条件保持不变。

默认算例:算术强度 20 FLOP/byte;计算下界 20ms;访存下界 100ms;总体理想下界 100ms。此估算受访存限制。
对照预测与反例

流量 10 GB 时下界 20ms;只把峰值从 100 提到 200 TFLOP/s,仍为 100ms。流量改变必须有可测机制,例如数据复用提高、临时张量减少或算子融合;不能只在计算器中改数字后宣布代码已优化。

时间之外,还要算“同时活着”的内存

带宽回答“搬得多快”,容量回答“能不能放下”。一个推理服务的显存可能同时容纳权重、生成请求的 KV、临时工作区和运行时开销。训练还会有梯度、优化器状态和激活,第 03 课会拆开计算。不能只算权重,就断言模型可以稳定运行。

以 7×10⁹ 参数、每参数 2 bytes 的权重为例,理论权重是 14 GB,约 13.04 GiB。这里 GB=10⁹ bytes,GiB=2³⁰ bytes。假设可供实验使用的容量是 22 GiB,KV 为 2 GiB,工作区与运行时预留为 3 GiB,则账面剩余约 3.96 GiB。这不是某型号显卡的实测容量,也不是该模型的部署保证。你还要观察峰值、动态 shape、缓存增长和分配碎片。

22 GiB 假设预算中,权重、KV、工作区和剩余空间的比例权重13.04GiB,KV2GiB,工作区与运行时3GiB,账面剩余3.96GiB。不同生命周期决定同时占用的峰值。22 GiB 可用预算 · 所有数值为教学假设权重 13.04 GiBKV 2 GiB · 工作区 / 运行时 3 GiB · 账面剩余 3.96 GiB峰值还取决于请求长度、批量、临时张量与分配行为。
图 02.2 · 这份内存账的重点是同时占用与余量。第 06 课会让你亲自推导 KV 项,而不是照抄 2 GiB。

发生 OOM 时,先定位它在哪个阶段出现。加载权重就失败,和请求增多后 KV 增长导致失败,是不同问题。增加并发可能提高利用率,也可能吃掉余量;减小单次批量可能缓解容量问题,但未必提高吞吐。优化动作必须对应你观察到的限制。

如果卡住,按证据缩小范围

从现象到下一条可核对的证据
现象先查什么有边界的试验
GPU 空闲间隙长CPU 与输入队列、数据读取时间固定样本,比较预处理后缓存与原输入
kernel 长,带宽项更大相关内存层流量、缓存与数据复用固定计算量,减少一次中间读写
很多极短 kernel 与间隙提交、同步和设备执行时间线减少一次同步,再核对正确性和端到端时间
只在长请求或大 batch OOM峰值内存、shape 与请求生命周期分别只改长度或 batch,记录出现阈值

有 GPU 的选做路线:固定模型、输入、精度、设备与版本,先做 warmup,再用相同统计窗口采集端到端时延和 Profiler 时间线。异步设备操作的计时必须明确同步或使用设备事件,CPU 发起调用所用的时间不能直接当作 kernel 时间。没有 GPU 时,就在本课的教学 trace 与计算模型中练习归因,并把报告标为机制实验。

把解释写成一份能被推翻的记录

交付一个三段记录:①观察边界和基线;②你认为最主要的限制及依据;③只改一个变量时的预测、实际结果和反证条件。浏览器计算与虚构 trace 只能证明你会解释模型,不证明某块 GPU 会获得对应收益。

  1. 复算与反例。把带宽从 1,000 改为 500 GB/s,保持其他默认值不变。写出新下界,再解释为何提高峰值算力不能解决这个例子的访存限制。
  2. 迁移到陌生任务。一个 kernel 为 8×10¹² FLOPs、20 GB 流量,设备条件仍为 100 TFLOP/s 与 1,000 GB/s。选“降低流量”还是“提高同精度算力”作为首先验证的方向?列出实际观测可能与模型不同的两个原因。
  3. 建立内存账。将上例 KV 从 2 改为 6 GiB,其余预算不变。解释为何账面超出约 0.04 GiB 已经不能按原假设运行;不要把只差一点当成可以忽略。
完成后再看参考与验收

带宽减半:访存下界 200ms,总下界 200ms。陌生 kernel:计算 80ms,访存 20ms,先验证计算项;启动开销、并行不足、真实流量/峰值不匹配都可能让实测更慢。内存账:13.04+6+3≈22.04 GiB,超出 22 GiB 假设预算;必须改变并发/长度/表示或容量,并测峰值,不能依靠四舍五入过关。

怎样算完成:单位与观察范围清楚;预测可复算;能指出一个错误解释;明确什么证据会推翻当前假设。自由文本需要你按这些条件自检。

陌生任务的模型下界主要由哪一项决定?

带着一个问题读官方说明

NVIDIA · GPU Performance Background:先找 arithmetic intensity 与 memory/compute limited 的判断。读前写下你认为提高算力会有效的条件;读后用本课两个 kernel 解释边界,再列出该模型没有覆盖的执行开销。无需把全文的架构参数背下来。

下一步:训练多出来的状态是什么?

你现在会把时间与内存分开,也知道一个权重大小数字不足以证明能跑。训练除了权重,还要保存梯度、优化器和激活;第 03 课会从一个实际更新步说明这些状态为什么存在,以及减小 batch 与梯度累积各改变什么。

留下本课的产出

本课产出:一份瓶颈假设与反证记录。写下条件、证据、结果和仍不确定的事。保存不代表自动通过,下面的状态由你按验收条件自检。

记录只保存在当前浏览器。

按验收条件自检