CUDA 编程不要按“语法课”学,要按 GPU 执行模型 → 内存层次 → 性能建模 → Kernel 优化 → AI 算子实现 这条线学。你以后做 AI Infra / 推理优化,核心不是“会写 CUDA”,而是能判断:
一个算子为什么慢?瓶颈在访存、计算、同步、调度、还是数据布局?
怎么改 kernel / 改 layout / 改 fusion / 改 quantization 才能变快?
1. CUDA 编程的总知识框架
可以分成 8 层。
1 | CUDA 编程 |
2. 最先要理解:GPU 和 CPU 的差异
CPU 适合:
1 | 复杂控制流 |
GPU 适合:
1 | 大量相似计算 |
CUDA 编程的本质是:
把一个大任务切成很多小任务,让 GPU 上成千上万个线程并行执行。
比如向量加法:
1 | C[i] = A[i] + B[i] |
CPU 可能是一个 for 循环:
1 | for (int i = 0; i < N; i++) { |
CUDA 是让很多线程同时算:
1 | int i = blockIdx.x * blockDim.x + threadIdx.x; |
每个线程负责一个 i。
3. CUDA 最核心的执行层级
你必须熟悉这几个概念:
1 | Grid |
实际执行时还有一个更底层的概念:
1 | Warp = 32 个线程 |
NVIDIA GPU 上,warp 是调度的基本单位。也就是说,不是一个 thread 一个 thread 单独跑,而是 32 个线程一组执行。
所以 CUDA 性能优化经常围绕这些问题:
| 问题 | 含义 |
|---|---|
| thread 怎么映射数据? | 每个线程负责哪个元素 |
| block 多大? | 每个 block 有多少线程 |
| grid 多大? | 总共 launch 多少 block |
| warp 是否分歧? | 同一个 warp 内线程是否走不同分支 |
| 访存是否合并? | 相邻线程是否访问连续地址 |
| shared memory 是否冲突? | 是否发生 bank conflict |
| register 是否太多? | 是否影响 occupancy |
4. 内存层次是 CUDA 的核心
CUDA 优化大部分时候不是“算得不够快”,而是“数据搬得太慢”。
你要记住这个层次:
1 | register 最快,线程私有 |
粗略理解:
| 内存 | 作用 | 优化重点 |
|---|---|---|
| Register | 每个线程自己的变量 | 减少 register pressure |
| Shared Memory | block 内线程共享 | tile、复用数据、避免 bank conflict |
| Global Memory | 显存 HBM | 合并访存、减少访存次数 |
| L2 Cache | 全 GPU 共享缓存 | 数据复用、cache locality |
| Host Memory | CPU 内存 | 减少 CPU-GPU 拷贝 |
AI Infra 里很多优化本质上是:
减少 global memory 读写,把数据尽量放在 register / shared memory 中复用。
例如 FlashAttention 的核心思想之一就是避免把完整 attention matrix 写回 HBM。
5. 你应该按什么顺序学
第一阶段:CUDA 基础语法
目标:能写简单 kernel。
需要掌握:
1 | __global__ kernel |
练习:
| 练习 | 目的 |
|---|---|
| vector add | 理解 thread indexing |
| scalar multiply | 理解 elementwise |
| ReLU | 对应深度学习 elementwise op |
| sigmoid | 理解数学函数 |
| matrix add | 理解 2D indexing |
这一阶段不要急着优化,先把 CUDA execution model 搞清楚。
第二阶段:内存访问和性能基础
目标:知道为什么 kernel 慢。
重点学:
1 | coalesced memory access |
你要重点理解:
Coalesced Access
好访问:
1 | thread 0 -> A[0] |
坏访问:
1 | thread 0 -> A[0] |
GPU 喜欢相邻线程访问连续地址。
这对 AI 里的 layout 很重要,比如:
1 | [N, C] |
不同 layout 会影响 attention / KV cache / quantized linear 的访存效率。
第三阶段:经典并行模式
目标:能写常见并行算法。
重点练:
| 模式 | 代表算子 |
|---|---|
| elementwise | ReLU, GELU, RoPE |
| reduction | sum, max, LayerNorm |
| scan | prefix sum |
| transpose | layout transform |
| tiled matmul | GEMM |
| histogram | sampling / token 统计 |
| top-k | decoding / sampling |
其中对 LLM 推理最重要的是:
1 | reduction |
第四阶段:写 AI 算子
这阶段开始进入你的主线:AI Infra。
建议按这个顺序实现:
1 | 1. ReLU / GELU |
每个算子都要问 5 个问题:
1 | 输入 shape 是什么? |
6. 对 AI Infra 最重要的 CUDA 算子
1. RMSNorm / LayerNorm
LLM 中大量出现。
形式大概是:
1 | RMSNorm(x) = x / sqrt(mean(x^2) + eps) * weight |
核心是 reduction:
1 | sum(x_i^2) |
难点:
1 | 一个 token 的 hidden_dim 通常很大 |
你可以先写:
1 | 每个 block 处理一个 token |
2. Softmax
Attention 中核心算子。
公式:
1 | softmax(x_i) = exp(x_i - max(x)) / sum(exp(x_j - max(x))) |
需要两个 reduction:
1 | max reduction |
优化重点:
1 | 数值稳定性 |
3. RoPE
RoPE 本质是对 Q/K 做旋转位置编码。
简化理解:
1 | x1' = x1 * cos - x2 * sin |
这个算子偏 elementwise,瓶颈通常是访存。
重点:
1 | 连续访存 |
4. Quantized Linear
这是你做推理优化会非常常见的东西。
例如 W8A16:
1 | activation: fp16 / bf16 |
计算逻辑:
1 | Y = X @ dequant(W) |
或者:
1 | Y = X @ W_int8 * scale |
重点问题:
1 | scale 是 per-tensor / per-channel / per-group? |
这块和你之前学的量化、ONNX、推理导出关系很大。
5. Attention / FlashAttention
普通 attention:
1 | QK^T -> softmax -> P V |
问题是 QK^T 很大。
例如 sequence length = 8192:
1 | attention matrix = 8192 × 8192 |
非常吃显存带宽。
FlashAttention 的思想是:
1 | 不要把完整 attention matrix 写回 HBM |
这就是 CUDA 编程和 AI Infra 的典型交叉点。
7. 你应该掌握的 CUDA 性能分析工具
只会写 kernel 不够,必须会 profile。
必学工具
| 工具 | 用途 |
|---|---|
| Nsight Systems | 看整体时间线、CPU-GPU overlap、kernel launch |
| Nsight Compute | 看单个 kernel 的性能指标 |
| nvprof | 老工具,了解即可 |
| ncu | Nsight Compute CLI |
| nsys | Nsight Systems CLI |
你需要会看这些指标:
1 | kernel duration |
尤其是:
1 | Memory Bound? |
AI Infra 里优化时经常要判断:
1 | 这个 op 值不值得手写 CUDA? |
8. CUDA 和 PyTorch / ONNX / TensorRT 的关系
你现在学的东西可以这样串起来:
1 | PyTorch Model |
CUDA 在最底层。
比如一个 PyTorch op:
1 | y = torch.nn.functional.layer_norm(x) |
底层可能变成:
1 | PyTorch dispatcher |
如果你写自定义算子:
1 | Python API |
如果你导出到 ONNX:
1 | ONNX op |
如果你做 TensorRT plugin:
1 | TensorRT engine |
所以你的目标不是单独学 CUDA,而是学:
CUDA kernel 如何嵌入到 AI 推理系统里。
9. 建议学习路线:按 10 周推进
第 1-2 周:CUDA 基础
目标:
1 | 能写、编译、运行简单 CUDA kernel |
任务:
1 | vector add |
掌握:
1 | threadIdx / blockIdx |
第 3-4 周:内存与优化
目标:
1 | 理解为什么 CUDA kernel 快或慢 |
任务:
1 | 连续访存 vs stride 访存 benchmark |
掌握:
1 | coalescing |
第 5-6 周:矩阵乘法
目标:
1 | 理解 GEMM 是如何优化的 |
任务:
1 | naive matmul |
需要理解:
1 | M, N, K |
不要一开始就追求写出 cuBLAS 级别 GEMM。这个很难。目标是理解它为什么需要 tiling。
第 7-8 周:LLM 算子
目标:
1 | 能实现几个小型 LLM CUDA kernel |
任务:
1 | RMSNorm |
重点:
1 | reduction |
第 9 周:PyTorch Extension
目标:
1 | 把 CUDA kernel 接进 PyTorch |
学习:
1 | torch.utils.cpp_extension |
你要能写这种接口:
1 | import my_cuda_ops |
然后和 PyTorch 原生实现比较:
1 | torch.cuda.Event benchmark |
第 10 周:推理系统结合
目标:
1 | 理解 CUDA kernel 在推理框架中的位置 |
练习:
1 | 给一个 Qwen / LLaMA block 替换 RMSNorm kernel |
这时你就能把 CUDA 和你正在学的:
1 | ONNX |
串起来。
10. 最推荐的练习项目
按价值排序:
Project 1:手写 RMSNorm CUDA Kernel
难度适中,和 LLM 强相关。
功能:
1 | y = rmsnorm(x, weight, eps) |
输入:
1 | x: [batch, seq_len, hidden_dim] |
优化版本:
1 | v1: naive |
你可以和 PyTorch 版本 benchmark。
Project 2:手写 Softmax Kernel
功能:
1 | y = softmax(x, dim=-1) |
重点:
1 | max reduction |
这是理解 attention kernel 的前置知识。
Project 3:手写 Tiled MatMul
功能:
1 | C = A @ B |
版本:
1 | v1: naive global memory |
这能帮你理解为什么 GEMM 优化复杂。
Project 4:简化版 Attention
功能:
1 | Q, K, V -> Attention Output |
先不要直接写 FlashAttention。
先写:
1 | QK^T |
然后思考为什么它慢:
1 | 中间矩阵太大 |
再学 FlashAttention 才能真正理解。
Project 5:W8A16 Quantized Linear
功能:
1 | Y = X @ W_int8 * scale |
重点:
1 | int8 weight |
这和你实习方向非常贴合。
11. 学 CUDA 时最容易踩的坑
坑 1:只学语法,不学性能模型
会写:
1 | __global__ void kernel(...) |
不代表会 CUDA。
真正重要的是:
1 | 这个 kernel 为什么快? |
坑 2:一上来就学 Tensor Core
Tensor Core 很重要,但不适合最开始学。
顺序应该是:
1 | 普通 CUDA thread |
否则容易只记 API,不理解为什么这么设计。
坑 3:忽略数据 layout
AI kernel 很多性能问题来自 layout。
比如 KV cache:
1 | [B, S, H, D] |
不同 layout 对 decode 阶段的访问效率差异很大。
你要经常问:
1 | 连续维度是谁? |
坑 4:不做 benchmark
CUDA 学习必须伴随 benchmark。
每写一个 kernel,都要比较:
1 | PyTorch baseline |
同时检查:
1 | 正确性 |
12. 和 Triton 的关系
你之后大概率也要学 Triton。
可以这样理解:
| CUDA | Triton |
|---|---|
| 更底层 | 更高层 |
| 控制力强 | 开发效率高 |
| 学习成本高 | 更适合快速写 AI kernel |
| 适合极致优化 / 特殊场景 | 适合大多数深度学习算子 |
| 必须理解硬件细节 | 仍然需要性能模型 |
建议顺序:
1 | 先学 CUDA 基础 |
原因是:
Triton 把很多底层细节封装了,但你不懂 CUDA 性能模型,就不知道 Triton block size、num_warps、num_stages 为什么影响性能。
13. 你要形成的最终能力
学完 CUDA 后,你应该能做到:
1 | 1. 看懂一个 CUDA kernel 在干什么 |
对 AI Infra 岗位来说,最关键的是这 4 项:
1 | 性能建模 |
14. 最简学习路径总结
你可以按这个顺序学:
1 | CUDA 基础语法 |
更具体一点:
1 | 第一步:写 vector add / ReLU |
15. 对你当前方向的建议
你现在在学:
1 | ONNX |
所以 CUDA 不要学成“图形学 CUDA”或者“通用 HPC CUDA”。你应该直接围绕 LLM 推理学。
优先级应该是:
1 | RMSNorm > Softmax > RoPE > KV Cache > Quantized Linear > Attention > GEMM |
GEMM 很重要,但工业界通常优先用:
1 | cuBLAS |
你短期内更值得手写的是:
1 | 小算子 |
因为这些更贴近推理优化岗位里的实际工作。