跳转至

GPU 与系统

理解 GPU 不能只看“有多少核”和峰值 FLOPS。AI 工作负载最终受计算吞吐、显存容量与带宽、互连、数据供给和软件栈共同约束。

从请求到硬件的栈

flowchart TB
    A[PyTorch / JAX / 推理引擎] --> B[算子图 / 编译器]
    B --> C[CUDA Runtime / Libraries]
    C --> D[Kernel / Stream / Event]
    D --> E[SM / Tensor Core]
    D --> F[HBM / Cache]
    E <--> G[NVLink / PCIe / NIC]
典型对象 排查问题
框架 tensor、op、autograd、graph 是否产生了多余算子、同步或数据拷贝?
Runtime stream、event、allocator kernel 是否并发,是否隐式同步,显存是否碎片化?
Kernel grid、block、warp occupancy、访存合并、算术强度是否合理?
硬件 SM、Tensor Core、HBM、L2 受计算、带宽、延迟还是容量限制?
互连 PCIe、NVLink、RDMA 通信量是否匹配拓扑,是否跨慢链路?

三个容量概念

计算吞吐

峰值 FLOPS 只有在数据类型、算子形状和内核都能有效使用对应计算单元时才有意义。小矩阵、动态形状、频繁 kernel launch 或低算术强度都可能让峰值不可达。

显存容量

训练时的显存大致由以下部分组成:

\[ M_{train} \approx M_{param} + M_{grad} + M_{optim} + M_{activation} + M_{workspace} \]

其中激活随 batch、序列长度、层数和是否 activation checkpointing 明显变化;优化器状态随优化器与精度策略变化。所谓“每参数固定多少字节”只能做初筛,不能替代实测。

显存带宽

如果算子每做少量计算就需要搬运大量数据,它更可能受带宽限制。Roofline 模型用算术强度(FLOPs/Byte)连接峰值算力与内存带宽:

\[ P \le \min(P_{peak},\ I \times BW_{memory}) \]

GPU 执行要点

  • Kernel 异步执行:CPU 发射 kernel 后可继续工作;不必要的 .item()、同步计时或设备间拷贝会破坏流水。
  • Stream:同一 stream 内有序,不同 stream 可在依赖允许时并发;事件用于表达跨 stream 依赖。
  • Warp/SIMT:分支发散会让同一 warp 的不同路径串行化。
  • Tensor Core:矩阵形状、数据类型与库实现决定是否有效使用。
  • Allocator:框架常使用缓存分配器;“reserved 高”不等于当前 tensor 真正占满,碎片化也可能导致 OOM。

拓扑先于卡数

多 GPU 性能取决于通信对落在哪条链路。先查看:

nvidia-smi topo -m
nvidia-smi -L
lspci -tv
numactl --hardware

需要回答:

  • GPU 之间走 NVLink/NVSwitch 还是 PCIe?
  • GPU 到 NIC 是否在同一 NUMA/PCIe 根复合体附近?
  • CPU 线程和数据加载进程是否跨 NUMA 访问内存?
  • 容器看到的 GPU 顺序是否与物理拓扑一致?

别把 utilization 当成结论

GPU utilization 往往表示采样窗口内是否有 kernel 活跃,不能直接等价为“接近峰值算力”。组合观察:

证据 用途
SM active / Tensor Core 活跃 计算单元是否被有效使用
DRAM active / 显存带宽 是否为内存带宽瓶颈
PCIe/NVLink 吞吐 是否在通信或主机拷贝
功耗与时钟 是否降频、限功耗或空转
kernel timeline 是否存在气泡、同步和大量小 kernel
step/request 分解 硬件现象是否真的影响用户指标

NVIDIA DCGM 提供 GPU telemetry、健康诊断、拓扑和作业级统计,适合集群持续观测;深度性能定位再使用 PyTorch Profiler 或 Nsight Systems。

快速诊断顺序

  1. 固定工作负载与版本,确认结果可复现。
  2. 把端到端时间拆成 CPU/Data、H2D、kernel、collective、checkpoint/response。
  3. 看时间线是否有空洞或同步点。
  4. 对热点 kernel 判断 compute-bound 或 memory-bound。
  5. 再调整 batch、精度、融合、编译、拓扑或并行方式,每次只改变少量变量。

延伸阅读