10. 推理性能问题一般怎么排查?

整理推理性能问题的排查思路与常见瓶颈。

简单回答

推理性能排查的思路是先定位瓶颈在 Prefill 还是 Decode、在计算还是访存还是通信,然后对症下药。核心手段包括:分析 TTFT 和 per-token latency 定位阶段、用 GPU profiler(如 Nsight Systems)分析 GPU 利用率和 kernel 执行情况、检查 batch 大小和调度效率、排查显存使用和 KV Cache 管理、以及检查系统层面的开销(网络 IO、CPU 瓶颈、排队延迟)。

详细解释

排查的总体思路

推理性能问题表现为"太慢"或"吞吐太低",但背后的原因可能完全不同。不能一上来就调参数,要先搞清楚慢在哪里。

先分阶段:把 TTFT(首 token 时间)和 generation latency(后续 token 生成速度)分开看。如果 TTFT 高但 per-token 速度正常,瓶颈在 Prefill——可能是 Prompt 太长、或者 Prefill 没有被高效调度。如果 TTFT 正常但 per-token 速度慢,瓶颈在 Decode——可能是访存瓶颈、batch 太小 GPU 利用率低。

再分层次:GPU 计算层面(kernel 执行效率)、显存层面(KV Cache 管理、显存碎片)、调度层面(batch 效率、Continuous Batching 是否正常工作)、系统层面(CPU 处理瓶颈、网络 IO、进程间通信)。

GPU 利用率分析

nvidia-smi 粗看 GPU 利用率和显存使用。如果 GPU Utilization 远低于 100%,说明 GPU 算力没有被充分利用。常见原因:batch 太小(Decode 阶段一个 token 的计算量太小无法喂满 GPU)、CPU 预处理成为瓶颈(tokenization、数据准备太慢导致 GPU 在等)、调度不合理(GPU 有空闲但没有及时调入新请求)。

更深入的分析需要用 NVIDIA Nsight Systems 或 PyTorch Profiler。Nsight Systems 可以看到每个 CUDA kernel 的执行时间、kernel 之间的间隙(如果有大段空闲说明有等待)、CPU 和 GPU 的执行时间线对比。

Prefill 阶段的性能问题

Prefill 是计算密集型的。如果 Prefill 慢,看 Prompt 长度是否过长——Prefill 的计算复杂度是 (因为 self-attention),4096 token 的 Prompt 比 512 token 慢约 64 倍。考虑是否可以缩短 Prompt、或者用 Prompt Caching 避免重复 Prefill。

另一个 Prefill 相关的问题是 chunked prefill 的 chunk 大小设置。如果 chunk 太小,Prefill 会被分成很多小步,每步之间有调度开销。如果 chunk 太大,会阻塞正在 Decode 的请求,增加它们的延迟。

Decode 阶段的性能问题

Decode 阶段是访存密集型的。per-token latency 主要取决于模型大小(参数越多读取越慢)和显存带宽。如果 per-token latency 接近"理论最优"(模型大小 / 显存带宽),说明已经打到硬件瓶颈了,优化空间有限,只能通过量化减小模型大小。

如果 per-token latency 远高于理论最优,可能有其他问题:KV Cache 管理不高效(频繁分配释放的开销)、CUDA kernel 不够优化、batch 大小太大导致 KV Cache 读取量过大。

调度和系统层面

检查 Continuous Batching 是否正常工作——有没有请求在排队却 GPU 有空闲的情况。检查 Prefill 和 Decode 的调度是否合理——是不是 Prefill 长时间占用 GPU 阻塞了 Decode 请求。

检查 CPU 是否成为瓶颈——tokenization、输入输出处理、调度逻辑如果在 CPU 上执行太慢,GPU 就会空闲。特别是 tokenization 如果用的是 Python 实现的 slow tokenizer,在高并发下可能成为瓶颈,换成 Rust 实现的 fast tokenizer 可以解决。

网络 IO——如果推理服务和客户端之间的网络延迟高,即使 GPU 处理很快,端到端延迟也会高。Streaming 输出时 SSE 的开销、每个 token 一个 HTTP 事件的序列化开销等都要考虑。

建立性能基线

排查性能问题最重要的前提是有基线(baseline)。在系统上线前先做 benchmark,记录在不同并发、不同 Prompt 长度、不同输出长度下的 TTFT、per-token latency、吞吐量。之后出现性能问题时和基线对比,就能快速发现是哪个维度恶化了。

面试时可以这样答

排查推理性能问题我一般按这个思路来。先分阶段——看 TTFT 和 per-token 延迟哪个不正常,定位是 Prefill 瓶颈还是 Decode 瓶颈。Prefill 慢通常是 Prompt 太长或 Prefill 调度不合理。Decode 慢通常是访存瓶颈或 batch 效率低。

然后看 GPU 利用率。用 nvidia-smi 粗看,GPU 利用率低说明算力没喂满——可能 batch 太小、CPU 预处理太慢、或调度有问题。深入分析用 Nsight Systems 看 kernel 执行和 GPU 空闲间隙。

还要排查系统层面——tokenizer 是不是用了慢版本、网络 IO 有没有开销、Continuous Batching 调度是否正常。

最重要的是有性能基线。上线前在不同负载下做 benchmark 记录各项指标,出问题时和基线对比就能快速定位哪个维度恶化了。

常见追问

  1. 你实际排查过什么推理性能问题?怎么解决的?
  2. Nsight Systems 的 profiling 结果怎么看?
  3. CPU 成为瓶颈的情况多吗?通常是什么操作导致的?