LLM Infer Infra 学习资料库

GPU 与 kernel 基础:带宽、异步拷贝与性能分析

Serving 与性能 · vLLM 性能与分布式 · 数据传输 · 实测与演练记录

KV 存储岗位不要求你手写高性能 attention kernel,但必须看得懂 GPU 在做什么:为什么 Decode 慢在读显存,为什么异步拷贝要用锁页内存,“拷贝完成”在 GPU 上到底怎么判断。这一页把这些基础讲清楚,并接到 KV 传输和性能分析上。

一句话结论:先判断瓶颈是算力、显存带宽、PCIe/网络,还是 CPU 发射;再看 KV 的读写落在哪条路径上。GPU 上“提交了”和“完成了”是两回事,要靠 stream 和 event 来确认。

1. GPU 的基本结构

概念白话解释和推理的关系
SM(流式多处理器)GPU 的“核心组”,一块 GPU 有上百个一个 kernel 的工作被分给许多 SM 并行执行
线程块 / warpkernel 按线程块分配到 SM;32 个线程组成一个 warp,同步执行同一条指令访存是否“合并”、分支是否一致,直接影响效率
寄存器、共享内存SM 内部最快的存储,容量很小FlashAttention 等 kernel 把数据分块放在这里反复使用
L2 缓存所有 SM 共享的缓存,几十 MB 量级小的热点数据可以留在这里
HBM(显存)容量最大(几十 GB),但比片上存储慢得多权重和 KV Cache 都在这里,Decode 主要被它的带宽限制
Copy Engine专门负责 CPU↔GPU 拷贝的硬件单元拷贝可以和计算同时进行,前提是用对了 stream 和锁页内存

以 H100 SXM 为例,公开规格约为:132 个 SM、50 MB L2、80 GB HBM3、约 3.35 TB/s 显存带宽、BF16 稠密算力约 989 TFLOPS。具体型号和频率不同,数字会变;下面的算例只用来说明方法。

2. Roofline:判断是“算得慢”还是“读得慢”

一个计算每读 1 字节数据能做多少次浮点运算,叫算术强度(FLOP/byte)。GPU 的“平衡点”约等于 算力 ÷ 带宽:

H100 SXM:989 TFLOPS ÷ 3.35 TB/s ≈ 295 FLOP/byte
算术强度 < 295:受显存带宽限制(读得慢)
算术强度 > 295:受算力限制(算得慢)

2.1 为什么 Decode 受带宽限制

Decode 每一步,每个请求只新增一个 token。线性层要把整份权重读一遍,但每个权重只和 batch 里的几个 token 相乘。粗略地说,batch 为 B 时,线性层的算术强度约为 B FLOP/byte(BF16 权重,忽略激活)。B 远小于 295 时,GPU 大部分时间在等数据。

8B 参数、BF16 权重 ≈ 16 GB
每步至少读一遍权重:16 GB ÷ 3.35 TB/s ≈ 4.8 ms
batch = 1 和 batch = 32 时,这 4.8 ms 基本一样 → 批处理能大幅提高吞吐

2.2 KV 也在抢带宽

Decode 时,attention 要把这个请求已有的全部 KV 读一遍。以资料中的示例模型(每 token 128 KiB)为例:

8K 上下文的 KV = 1 GiB
每步每个请求读 1 GiB:1.07 GB ÷ 3.35 TB/s ≈ 0.32 ms
32 个这样的请求 ≈ 10 ms,已经超过读一遍权重的时间

所以长上下文的 Decode 常常被 KV 读取限制。这也是 GQA、MLA、KV 量化能提速的原因:它们减少了每步要读的字节数。KV 存储的设计会直接影响 Decode 速度,而不只是影响 Prefill 能不能跳过。

2.3 Prefill 通常受算力限制

Prefill 一次处理很多 token,权重被反复使用,算术强度高,通常受算力限制。这也是“加载 KV 代替重算 Prefill”能省时间的来源:用带宽换算力。

3. kernel 为什么要融合

每个 kernel 都要从 HBM 读输入、把结果写回 HBM。两个小 kernel 连续执行,中间结果要写一次再读一次。把它们合成一个 kernel,中间结果留在寄存器或共享内存里,就省掉这次往返。FlashAttention 就是这个思路:不把完整的注意力矩阵写回 HBM。

另外,每次启动 kernel 都有 CPU 侧开销(微秒级)。Decode 每步有上百个小 kernel 时,CPU 发射可能成为瓶颈,GPU 在等 CPU。CUDA Graph 把一串 kernel 预先录制好、一次提交,用来减少这部分开销。

4. stream 与 event:判断“完成”的正确方式

这一节和 KV 存储的生命周期协议直接相关。

加载 KV 的正确顺序(概念):
1. 在拷贝 stream 上提交 H2D:host buffer → GPU 页
2. 在拷贝 stream 上记录 event E
3. 计算 stream 等待 E,再启动使用这些页的 attention
4. 只有 E 完成后,才允许释放或复用 host buffer

常见错误:CPU 提交拷贝后立刻释放 host buffer;计算 stream 没有等待拷贝 event 就开始读 KV;超时后直接复用正在被 DMA 写入的页。这些错误不一定每次都出现,出现时往往是“偶发的错误输出”,很难排查。

5. CPU↔GPU 之间的拷贝

5.1 锁页内存

普通(可分页)内存可能被操作系统换出,GPU 的 DMA 不能直接访问。用可分页内存做拷贝时,驱动通常要先复制到内部的锁页缓冲区,无法真正与计算重叠。要实现异步、可重叠的拷贝,host 侧 buffer 应该是锁页内存(pinned memory)。

代价:锁页内存不能被换出,占用过多会挤压系统其他进程。缓存系统通常预先分配一大块锁页内存再自己管理,而不是每次临时申请。RDMA 注册内存也是类似的道理。

5.2 PCIe 带宽

PCIe Gen4 x16:理论约 32 GB/s 每方向,实际常见约 25 GB/s
PCIe Gen5 x16:理论约 64 GB/s 每方向,实际常见约 50 GB/s
1 GiB KV 走 Gen4(按 24 GiB/s)≈ 42 ms

更多 GPU、PCIe 和网卡的公开数据见公开参考数据。H2D 往往和网络一样是 KV 加载的瓶颈。多块 GPU 共用一个 PCIe 交换芯片、或网卡和 GPU 不在同一 NUMA 节点时,实际带宽会更低。用 nvidia-smi topo -m 查看 GPU、网卡之间的拓扑。

5.3 GPUDirect RDMA

在支持的硬件和驱动上,网卡可以直接读写 GPU 显存,跳过 host 内存这一步(GDR)。它能省掉一次 H2D/D2H 拷贝,但要求注册 GPU 内存、拓扑合适,且并不是所有缓存集成路径都使用它。分析时要画出真实路径:数据到底有没有经过 host。

6. 性能分析工具怎么用

工具看什么典型发现
Nsight SystemsCPU 和 GPU 的时间线:kernel、拷贝、同步、空闲GPU 有大段空白 → CPU 发射或调度慢;拷贝和计算没有重叠
Nsight Compute单个 kernel 的指标:带宽利用率、算力利用率、占用率attention kernel 只用到 40% 带宽 → 访存模式有问题
torch.profilerPyTorch 层面的算子耗时与调用栈快速定位哪段 Python 代码触发了慢操作或同步
nvidia-smi显存占用、利用率、拓扑、链路信息确认 PCIe 代数与宽度、显存是否接近上限

计时陷阱:GPU 是异步的,用 CPU 计时前必须同步,或者用 CUDA event 计时;第一次运行包含初始化和编译,要先预热;要报告多次测量的分布,而不只是一次结果。

7. 写和评估 kernel 的基本要求

即使不以写 kernel 为主,也应该知道评估一个 kernel 优化的标准流程:

  1. 正确性:与参考实现(如 PyTorch)对比输出,在代表性 shape 和 dtype 下检查误差。
  2. 代表性 shape:用真实部署中的 batch、序列长度、head 数,而不是只测一个“好看”的形状。
  3. 上限对比:把实测带宽或算力和硬件峰值比较,判断还有多少空间。
  4. 端到端影响:kernel 快 20%,若只占请求时间的 10%,整体只快约 2%。

常见写法有 CUDA C++、Triton 等。入门可以从一个“按 block table 收集分页 KV 到连续 buffer”的 kernel 开始,它正好对应 KV 保存时的 gather 操作。

8. 面试怎么答

问题回答要点
为什么 Decode 的吞吐随 batch 增大而上升?Decode 受显存带宽限制,每步读一遍权重的成本被 batch 内的请求分摊;batch 继续增大后,KV 读取和算力会逐渐成为新瓶颈
为什么长上下文 Decode 变慢?每步要读该请求全部 KV,KV 随上下文线性增长;GQA、MLA、KV 量化通过减少字节数缓解
H2D 拷贝为什么没有和计算重叠?可能用了可分页内存、拷贝和计算在同一 stream、或中间有隐式同步;用 Nsight Systems 看时间线确认
怎样确认 KV 已经可以被 attention 使用?拷贝所在 stream 记录 event,计算 stream 等待该 event;host buffer 在 event 完成后才释放
kernel 快了 30%,服务为什么没变快?它可能不在关键路径上,或只占很小比例;要用端到端指标和时间线验证

继续深入:vLLM 性能、分布式与服务工程(FlashAttention、CUDA Graph、并行与量化);动手测量见实测与演练记录。

输入主题、术语或问题