CUDA 执行模型:内核、流与图,以及故障签名
你不需要写 CUDA 程序,但你需要知道一次“GPU 计算”由哪些动作组成、每一层故障长什么样,否则排障时你只能重启。
本章补齐从微架构到Kubernetes 管理模型之间缺失的一层:CUDA 运行时如何把计算落到 GPU 上。理解这一层,可观测里的指标、故障模式里的报错、vLLM 的参数才都有出处。
一次计算的完整旅程:host 与 device
GPU 是 CPU 的协处理器,不能独立工作。以向量加法 C = A + B 为例,完整路径是:
cudaMalloc在显存里分配 A、B、C;cudaMemcpy把数据从主机内存拷入显存(走 PCIe,约 64 GB/s);- CPU 发射 kernel(内核):一段在 GPU 上执行的函数,每个线程算一个元素;
cudaMemcpy把结果拷回主机;cudaFree释放。
要点:搬运与计算的代价同量级,且搬运路径比计算路径慢一个数量级以上。数据靠近 GPU(权重视驻显存、网络直达显存)是所有高性能栈的第一设计原则。
Kernel、grid、block:并行结构的声明
启动 kernel 时声明并行层级:grid(总并行度)→ block(放进 SM 的单位)→ thread(最小执行单元,32 个一组成为 warp)。可以用 Kubernetes 语言类比:kernel ≈ Job,block ≈ Pod(调度到某个 SM 的单位),thread ≈ 容器内进程。
平台工程师只需带走一句翻译:
一个 Python 训练/推理步骤 = 几十到上千个小 kernel 依次执行。 PyTorch 的每个算子(矩阵乘、LayerNorm、激活)就是一或多个 kernel。
Stream:GPU 内部的队列
stream(流)是 kernel 的执行队列:同流严格 FIFO,异流可并行(若 SM 有空闲)。陷阱在默认流:它会隐式同步其他所有流,框架以为在并行,实际被串行化。NCCL、数据加载、vLLM 内部都在精细管理多流;在火焰图里看到的每一行泳道就是一个 stream。
启动开销与 CUDA Graph:为什么推理引擎都在“录图”
每发射一个 kernel,CPU 要花 3–10 微秒准备。推理解码一步发射几百上千个小 kernel,启动开销可能超过计算本身:
每步 500 kernels × 5μs = 2.5ms 纯开销(常与计算同量级)CUDA Graphs 把一整步的 kernel 依赖“录制”成图,之后每步一次调用重放整图,启动开销从 N×5μs 降为一次几 μs。vLLM 默认对解码步做图捕获,--enforce-eager(关掉录图)会让小批量解码吞吐下降 10–40%。
对平台有两个连带影响:一张重放的图接近一个超长 kernel,会改变多租户时间片交错的粒度(见数据平面谱系);图捕获要求显存地址稳定,这影响引擎的显存布局策略(见显存管理)。
显存与上下文底噪
每个 CUDA 进程建立上下文(context)需常驻 0.3–0.8GB 显存(驱动、kernel 镜像、库工作区),未算任何张量。这解释了两个平台现象:一块卡上塞 20 个小进程会白白烧掉 6–16GB;以及“用 1 个推理引擎进程做多租户,优于 20 个小进程挤一块卡”。显存分配、缓存与碎片的完整机制见下一章GPU 显存管理。
故障签名:这一层的报错怎么读
| 报错/现象 | 含义 | 第一反应 |
|---|---|---|
CUDA out of memory | 显存不足(不是主机内存) | 走显存排查树 |
CUDA error: device-side assert | kernel 内断言(多为索引越界) | 应用 bug,非平台问题 |
CUDA driver version is insufficient | 驱动与 CUDA 运行时不匹配 | 版本治理,见管理模型 |
illegal memory access | 显存越界 | 应用 bug;偶发则查 XID/ECC |
| 程序 hang 在 NCCL init | 通信初始化等不到对端 | 调度问题(部分启动),见调度问题域 |
| XID 错误码(dmesg/nvidia-smi -q) | 驱动级事件:13 显存错、43 降频、79 掉卡 | 纳入节点告警;79 级需隔离换卡 |
OOMKilled(exit 137)是主机内存问题(cgroup);进程内 CUDA out of memory 是显存问题(绕过 cgroup)。两个 OOM、两套排查树,混在一起是 GPU 平台最高频的误诊。总结
CUDA 执行模型给平台工程师的三件事:一次步骤 = 一串 kernel(所以有启动开销与 CUDA Graph);stream 是 GPU 内部队列(所以并行可能被默认流悄悄串行化);这一层的故障有稳定签名(XID、两类 OOM、NCCL hang),可以直接做成 runbook。它们分别通向显存管理、推理工作负载与故障模式手册。