CUDA系统拆解-12-面试总复盘:怎么把 CUDA 能力连接到 AI 推理
CUDA系统拆解-12-面试总复盘:怎么把 CUDA 能力连接到 AI 推理
本文是「CUDA系统拆解」系列第 12 篇。
系列导读:CUDA系统拆解-00-导读:从编程模型到 AI 推理系统的学习路线
上一篇:CUDA系统拆解-11-经典CUDA算子模式:elementwise、reduction、reorder 与 blocked compute
下一篇:CUDA系统拆解-13-面试强化专题:PTX、Tensor Core、CUTLASS 与 Triton 怎么讲
1. 这篇解决什么问题
- 学到这里,你到底应该具备哪些能力。
- 为什么 AI 推理岗位会反复问 CUDA。
- 怎样把前面学过的内容整理成
算子层 / 执行层 / 系统层三层框架。 - 看到一个慢算子、一个 kernel、一个框架设计时,怎样把它还原成 CUDA 问题。
- 面试里怎样把
occupancy、coalescing、fusion、graph、batching讲成一套完整的系统理解。
2. 先记住的核心结论
- AI 推理优化的本质,不只是“算得快”,而是“算和搬,以及调度和资源管理一起做好”。
- CUDA 在推理岗位里重要,不是因为大家都要求你手写复杂 kernel,而是因为大量系统问题最后都能还原成 CUDA 的代价模型。
- 一套成熟的理解框架可以分成三层:
算子层、执行层、系统层。 - 看到慢算子时,要能还原成:线程怎么分工、数据怎么流动、同步和 launch 开销在哪里、GPU 为什么没吃满。
- 面试真正想听的不是 API 名字,而是你能不能说清楚:为什么这样设计、快在哪里、代价在哪里、边界在哪里。
- 高水平回答一定带 trade-off,而不是只有结论。
3. 正文讲解
3.1 学到这里应该具备哪些能力
如果前面 11 篇你真的吃进去了,现在应该不只是“知道一些 CUDA 名词”,而是至少具备下面几种能力。
第一,看到一个 kernel,能快速判断它在干什么。
也就是能回答:
- 一个线程负责什么
- 一个 block 为什么这样切
- 它更像
elementwise、reduction、reorder还是blocked compute - 主要瓶颈更像带宽、同步、算力还是 launch
第二,看到一个慢算子,能大致猜到问题可能在哪。
例如:
- reduction 慢,可能是同步和局部合并路径不好
- transpose 慢,可能是访存模式和
bank conflict - GEMM 慢,可能是 tile、复用或资源平衡不好
- decode 慢,可能是 kernel 太碎、launch 太重、memory latency 太明显
第三,看到一个推理框架设计,能把它拆成底层代价问题。
例如:
- continuous batching 在解决 GPU 吃不满
- fusion 在减少 global memory traffic 和 launch overhead
- paged attention 在做 KV cache 的内存组织和复用管理
- CUDA Graph 在减少 CPU 反复 launch 的开销
如果你已经能做到这三点,说明你学到的不是“概念列表”,而是分析框架。
3.2 为什么 AI 推理岗位会问 CUDA
很多人会误以为:
我做的是推理系统,不是专职内核工程,为什么还要学 CUDA?
原因很简单:推理系统的大量核心问题,最后都能落到 CUDA。
推理系统关心的通常是:
- 更低延迟
- 更高吞吐
- 更高 GPU 利用率
- 更低显存占用
- 更稳定的多请求并发
而这些目标背后,本质上都对应一些 CUDA 问题:
- 延迟为什么高:kernel 慢、launch 太碎、同步太多、调度有空泡
- 吞吐为什么上不去:GPU 没吃满、batch 不规整、copy / compute 没 overlap
- 显存为什么吃紧:activation、workspace、KV cache 和 allocator 策略
- GPU 利用率为什么不高:occupancy、stream 编排、request 调度、kernel 粒度
所以面试官问 CUDA,不是在确认你会不会 cudaMalloc,而是在确认:
你能不能把推理系统问题还原成底层执行和资源问题。
3.3 一套成熟的三层框架
我建议把前面的 CUDA 知识收束成三层。
算子层
- 关注单个算子怎么实现、为什么快、为什么慢
- 关键词通常是:线程映射、访存模式、shared memory、reduction、tiling、fusion
典型问题:
- GEMM 为什么适合 tile 化
- softmax 为什么是 reduction + elementwise
- LayerNorm 为什么常常
memory-bound - attention 为什么经常受 KV cache 访问和中间数据流影响
执行层
- 关注多个 kernel 和数据传输怎样组织
- 关键词通常是:stream、异步拷贝、pinned memory、overlap、launch overhead、CUDA Graph
典型问题:
- 为什么默认 stream 会把流水拉直
- 为什么 decode 场景更容易暴露 launch 开销
- 为什么 graph capture 对稳定重复路径有价值
系统层
- 关注请求调度、显存管理、并发策略、多 GPU 协作
- 关键词通常是:continuous batching、KV cache、paged attention、memory pool、通信重叠
典型问题:
- 为什么 continuous batching 能提高吞吐
- 为什么 KV cache 是推理系统里的核心状态
- 为什么 paged attention 的关键是管理灵活性和访问代价之间的平衡
这三层最大的价值在于:
你可以把系统层问题一路拆到执行层,再拆到算子层。
3.4 算子层:看到慢算子时如何还原成 CUDA 问题
算子层的核心不是公式,而是代价模型。
以后看到一个算子,先问:
- 它是
elementwise、reduction、reorder还是blocked compute - 它更像
memory-bound还是compute-bound - 中间结果主要留在寄存器、
shared memory还是频繁回写global memory
几个最典型的推理映射:
Linear / MLP
- 核心是 GEMM
- 真正关键的是 tile、复用、shared memory、寄存器和 tensor core 路径
softmax / LayerNorm / RMSNorm
- 本质是 reduction + elementwise
- 常见问题是中间结果回写多、同步多、launch 太碎
attention
- 本质是 GEMM-like 计算、reduction、reorder 和内存管理的组合
- 真正难点常在数据流和 KV cache 访问,而不只是公式
所以当面试官问你一个算子为什么慢时,不要只说“复杂度高”,而要说:
- 它在哪一层受限
- 是算得慢还是搬得慢
- 是复用不够还是 launch 太碎
3.5 执行层:为什么很多问题不是 kernel 本身慢
到了执行层,你要建立一个很重要的意识:
很多推理性能问题,不是单个 kernel 本身差,而是整条执行流水组织得差。
几个最典型的执行层因素:
stream
- 本质是设备端的有序任务队列
- 它决定哪些工作必须排队,哪些工作有潜在并发机会
异步拷贝和 pinned memory
- 不是为了 API 好看
- 而是为了让 H2D / D2H 与计算更容易 overlap
launch overhead
- 在 prefill 这种大算子场景里往往不明显
- 在 decode、小 batch、小 kernel 场景里会被迅速放大
CUDA Graph
- 本质是在减少 CPU 反复提交稳定路径的成本
- 适合稳定重复的执行图,不适合无限动态的一切场景
所以执行层最核心的提问方式是:
- GPU 是慢在算,还是慢在等
- 时间花在 compute、copy、sync,还是 host 调度
- overlap 到底成立了没有
3.6 系统层:为什么推理系统设计本质上是资源管理
到了系统层,很多话题表面看已经不像 CUDA,但底层逻辑还是一样。
最典型的是 KV cache。
KV cache 的本质是:
- 用显存换计算
- 让 decode 不必重复算历史 token
但这立刻会引出系统级问题:
- 显存怎么管
- 请求进进出出时怎么避免碎片
- 长上下文下怎么让访问仍可接受
paged attention 的重要性也在这里。
它真正解决的不是“分页”这个词,而是:
在动态请求和长上下文场景下,让 KV cache 更可管理、更可复用、更可扩展。
再比如 continuous batching。
它表面上是调度策略,底层本质却是:
- 让 batch 不至于过稀
- 让 GPU 一直有比较规整的活可做
- 缓解 decode 阶段小步长、小并行度带来的资源浪费
所以系统层真正关心的是:
- 工作怎么持续喂给 GPU
- 显存和缓存怎么被长期管理
- 通信、计算、copy、调度如何重叠
3.7 怎样把 occupancy、coalescing、fusion、graph、batching 连到推理系统
这一段是面试里最容易形成完整表达的地方。
occupancy
- 不是性能分数
- 在推理里它更像“延迟隐藏能力”的一个窗口
- decode、小 batch、小 kernel 时更容易显得不够
coalescing
- 不只是访存概念
- 它会直接影响 KV cache 访问、layout transform、attention 读取效率
fusion
- 不只是减少 kernel 数量
- 更重要的是减少中间结果写回
global memory的次数 - 在 LayerNorm、softmax、bias、activation 一类链式算子里尤其关键
graph
- 不只是“优化 launch”
- 它在推理里真正有价值的场景是重复、稳定、可 capture 的路径
batching
- 不只是把请求凑一起
- 本质是在系统层维持更好的 GPU 利用率和执行规整性
如果把它们串起来,你就会发现:
推理优化本质上是在同时管理并行度、访存效率、执行流水和系统动态性。
这就是面试里最值得讲出来的“整体观”。
3.8 面试回答为什么不能停留在 API 层
很多人的回答最大的问题是:
- 会报术语
- 会背定义
- 但没有代价模型
例如别人问:
- 为什么 fusion 能快
- 为什么 decode 难优化
- 为什么 paged attention 重要
如果你只回答:
- “因为减少 kernel 数量”
- “因为 decode 更复杂”
- “因为 paged attention 更适合长序列”
这种回答信息密度太低。
更好的回答必须包含三件事:
第一,它在解决什么问题。
第二,底层为什么会快或更稳。
第三,它的代价和边界是什么。
这就是为什么我一直强调:
面试回答重点应是代价模型和系统理解,而不是背 API。
3.9 一个通用的回答模板
以后你遇到任何 CUDA × 推理问题,都可以用下面这个模板组织:
第一步:先说它在解决什么问题。
例如:
- fusion 在解决中间结果频繁回写和 kernel 过碎
- continuous batching 在解决动态请求下 GPU 吃不满
- paged attention 在解决 KV cache 管理和碎片
第二步:再说底层为什么有效。
例如:
- 减少 global memory traffic
- 提高数据复用
- 减少 launch overhead
- 让 overlap 更容易成立
第三步:说收益。
- 更高吞吐
- 更低延迟
- 更稳的 GPU 利用率
- 更低显存压力
第四步:说代价或边界。
- 寄存器压力上升
- 动态 shape 更难做
- 实现复杂度更高
- 管理更复杂
这套模板非常适合面试,因为它天然带工程感。
4. 和 AI 推理的关系
这一篇本身就是在把 CUDA 和 AI 推理直接连起来。
如果只用一句话概括:
AI 推理中的很多高性能设计,表面上是在做系统、算子和调度,底层本质上都可以还原为 CUDA 的三个核心问题:线程如何组织、数据如何流动、延迟如何隐藏。
更具体一点:
- prefill 更像大算子吞吐问题
- decode 更像小步长、强动态、memory latency 和调度问题
- attention 是最好的桥梁,因为它同时包含 GEMM、reduction、重排、KV cache 和系统调度代价
- 高水平推理优化,本质上是跨越算子层、执行层、系统层一起做 trade-off
5. 常见误区
- 推理岗位不需要学 CUDA。不是,很多系统问题最后都能还原成 CUDA 代价模型。
- 学 CUDA 就是为了手写复杂 kernel。不是,更重要的是能读懂底层代价和系统边界。
- 面试只要会讲几个 API。不是,真正想听的是“为什么这样设计”。
- fusion、graph、batching 是系统技巧,和 CUDA 没关系。不是,它们本质上都在管理执行和数据流。
- occupancy 高、GPU 利用率高,就说明系统没问题。不是,QPS、首 token 延迟和 steady-state token latency 还取决于很多执行层和系统层因素。
- paged attention 只是一个框架名词。不是,它背后是典型的显存管理与访问代价权衡。
6. 复习自测
- 学到这里,你应该具备哪些能力?
- 为什么 AI 推理岗位会反复问 CUDA?
- 怎样用
算子层 / 执行层 / 系统层三层框架去理解推理系统? - 看到一个慢算子时,怎样把它还原成 CUDA 问题?
- 怎样把
occupancy、coalescing、fusion、graph、batching连成一套系统理解? - 为什么面试回答重点应该是代价模型和 trade-off,而不是背定义?
- prefill 和 decode 的瓶颈差异应该怎样讲?
- 为什么说很多推理创新,本质上都是更懂 GPU 代价模型?

