Skip to content

9. 最佳实践 ​

这一节把前面所有内容凝结成可执行的原则。无论你是写 CUDA kernel、调推理引擎,还是做 GPU 集群调度,这些原则都适用。

9.1 内存访问优先于计算优化 ​

GPU 的峰值算力很高,但内存带宽相对有限。很多时候 kernel 慢不是因为算得慢,而是因为等数据。

原则:

  • 先优化 global memory 访问模式(合并访问、减少读写);
  • 再用 shared memory 做 tiling 复用数据;
  • 最后才考虑指令级优化。

9.2 合理选择 block size ​

Block size 影响 warp 数量、occupancy 和 shared memory 使用。

常见选择:

  • 128、256、512:通用矩阵乘、卷积;
  • 1024:需要大量线程协作的场景,但可能降低并发 block 数。

选择原则:

  • 尽量是 warp size(32)的倍数;
  • 能让 SM 上同时驻留多个 block;
  • 不超过 shared memory 和寄存器限制。

9.3 避免 warp divergence ​

同一个 warp 内出现分支会导致串行执行。

避免方法:

  • 让分支基于 threadIdx.x / 32 或 block-level 索引,而不是 threadIdx.x % 2;
  • 把需要分支的逻辑放到 warp 之间,而不是 warp 内部。

9.4 平衡 occupancy 与寄存器使用 ​

高 occupancy 有助于 hiding 延迟,但:

  • 每个线程用太多寄存器,会减少可同时驻留的 warp 数;
  • 寄存器 spill 到 local memory 会严重降速。

原则:

  • 用 launch_bounds 或编译器提示限制寄存器;
  • 通过 Nsight Compute 查看 register usage;
  • 不要为了 occupancy 无限压缩寄存器,关键是有效计算吞吐。

9.5 Kernel Fusion:减少内存往返 ​

把多个小 kernel 合并成一个,避免中间结果写回 HBM。

典型例子:

  • Flash Attention 把 attention 的多个步骤融合;
  • LayerNorm + Activation + Gemm 融合成一个 kernel。

PyTorch 2.x 的 torch.compile 会自动做大量 fusion,底层通过 Triton 生成 kernel。推理服务(vLLM、TensorRT-LLM、SGLang)则普遍配合 CUDA Graph:把整个解码 step 的几十个 kernel 录制下来一次性提交,消除 per-kernel launch 开销——在小 batch 低延迟场景下,这一步往往比任何单 kernel 优化都值钱。

9.6 混合精度:FP16/BF16/FP8/FP4 ​

精度建议
FP32对数值敏感的部分(如 loss scaling、部分 norm)
BF16训练首选,动态范围大,稳定性好
FP16推理、混合精度训练
FP8H100+ 推理,部分训练(需 Transformer Engine)
MXFP8 / NVFP4Blackwell+ 权重与 KV Cache 压缩;微缩放让 4-bit 保持可用精度
FP4 / NVFP4B200/Rubin 推理量化,Rubin 起成为推理主力精度

原则:

  • 训练优先保证稳定,再追求速度;
  • 推理可以更大胆地量化;
  • 始终用 loss scaling 或梯度缩放防止 FP16 下溢。

9.7 使用成熟的库,避免重复造轮子 ​

场景推荐
矩阵乘cuBLAS、CUTLASS
卷积/AttentioncuDNN、Flash Attention
多卡通信NCCL
通用并行算法Thrust
自定义融合算子先 torch.compile / Triton / cuTile,再考虑 CUDA C++ / CUTLASS

原则:手写 CUDA kernel 是最后手段。先确认 cuBLAS/cuDNN 没有满足需求的实现,再确认 torch.compile/Triton 生成的 kernel 不够快。

9.8 Profile 驱动优化 ​

不要猜测瓶颈,要测量。

工具链:

  • nvidia-smi dmon:快速看利用率;
  • nsys:系统级时间线;
  • ncu:kernel 级深度分析;
  • DCGM:生产监控。

关注指标:

  • Memory throughput / peak bandwidth ratio:接近 1 说明内存瓶颈;
  • Tensor Core utilization:低说明没用到 Tensor Core;
  • Occupancy:低说明并发 warp 不够;
  • Warp stall reason:看是等待内存、等待指令还是同步。

9.9 Kubernetes 调度层面的最佳实践 ​

详细内容参见 Kubernetes GPU 调度,这里列出关键原则:

  • 训练任务优先使用整卡或 MIG 实例,避免 MPS 的资源争抢;
  • 推理任务按延迟要求选择 MIG/MPS/整卡;
  • 启用 GPU 拓扑感知调度,让需要 NCCL 的 Pod 落在 NVLink 全互联节点;
  • 监控 DCGM 指标,设置 Xid、温度、功耗告警;
  • 定期做显存碎片整理和节点轮换。

9.10 本节小结 ​

高效 GPU 使用的十条原则:

  1. 内存访问比计算更重要;
  2. Block size 选 128/256/512 的常见值;
  3. 避免 warp divergence;
  4. 平衡 occupancy 与寄存器使用;
  5. 能 fusion 就 fusion;
  6. 混合精度按场景选择;
  7. 优先用成熟库,不轻易手写 kernel;
  8. 用 Nsight / DCGM 驱动优化;
  9. 多租户环境按隔离性选 MIG/MPS;
  10. 监控比调参更重要。

下一节是面试题,检验你是否真正掌握了这些概念。

Released under CC-BY-SA-4.0 License.