真实面经题目 · 原创解析
AI Infra 中拿到一个慢算子时,如何判断是否值得优化,并选择 kernel 优化、算子融合、图优化或数据布局调整?
这题考慢算子优化的工程决策树,重点不是单独判断 Memory Bound 或 Compute Bound,而是先判断投入是否值得,再把 profile 证据映射到 kernel、融合、图优化和 layout 等不同路径。
真实面经题目 · 原创解析
这题考慢算子优化的工程决策树,重点不是单独判断 Memory Bound 或 Compute Bound,而是先判断投入是否值得,再把 profile 证据映射到 kernel、融合、图优化和 layout 等不同路径。
我会先判断这个算子是否真的值得优化,而不是看到慢就改。第一步做端到端 profile,确认它在目标模型、目标 batch、prefill/decode 阶段和真实流量 shape 下是不是稳定热点,优化后能不能显著影响 TTFT、单 token 延迟、吞吐、显存或成本;如果它只在一次调试输入里慢,或者占比很低,就不应优先投入。第二步拆瓶颈:估算 FLOPs 和访存字节,用 profiler 看带宽、FLOPS、SM/Tensor Core 利用率、stall reason、kernel launch 数量、同步等待和内存分配,判断是算力瓶颈、访存瓶颈、launch/调度开销、shape 特殊路径还是 layout 问题。第三步按瓶颈选方案:compute bound 优先考虑 Tensor Core 路径、tile、并行度和指令调度;memory bound 优先减少读写、提高复用、coalescing、cache 和低精度存储;小算子和重复读写多时考虑算子融合或图优化;跨算子 layout 反复转换时考虑统一数据布局。最后要用 correctness、精度、端到端收益、回归测试和灰度开关验证,避免只把一个 kernel benchmark 做快却让整体系统更复杂。
优化入口不是单个算子的绝对耗时,而是它对端到端目标的贡献。要看这个算子在真实模型、真实输入分布、目标硬件、目标并发和 prefill/decode 阶段里的占比,以及优化后理论上能撬动多少延迟、吞吐、显存或成本。如果热点不稳定、占比很低、已有成熟库可替代,或者业务瓶颈在调度和排队上,优先级就应降低。
优化前要建立可重复 benchmark:固定模型版本、shape、batch、dtype、warmup、CUDA stream、同步点和统计口径,区分单 kernel 时间、算子组时间和端到端请求时间。Nsight、NCU、框架 trace、自定义 timing 和日志要互相校验,避免把异步执行、首次编译、cache miss 或数据拷贝混进算子耗时。
慢算子至少可能有四类原因:算力瓶颈,例如 Tensor Core 没用好、tile 不合适、指令吞吐低;访存瓶颈,例如 DRAM/L2 带宽高、访存不合并、中间结果反复读写;调度和启动开销,例如很多小 kernel、同步过多、动态 shape 导致 launch 频繁;数据布局问题,例如 transpose、padding、对齐或格式转换吃掉收益。不同瓶颈对应完全不同的优化路径。
如果瓶颈确实在单 kernel 内部,才进入 kernel 级优化。compute bound 场景关注 Tensor Core、WMMA/MMA 或成熟库路径、分块、寄存器复用、occupancy、unroll 和分支;memory bound 场景关注 coalescing、向量化加载、shared memory/cache 复用、减少中间写回和更紧凑的数据类型。kernel 优化要先和 cuBLAS、cuBLASLt、CUTLASS 或框架算子比较,证明自定义实现有必要。
如果多个小算子之间反复读写显存,或者 launch 开销占比高,单独优化其中一个 kernel 可能收益有限。此时更适合做算子融合,把 bias、activation、scale、dequant、residual、norm 等操作合进主 kernel 或 epilogue;也可以通过静态图 pattern rewrite、常量折叠、内存规划和 CUDA Graph 减少调度开销。融合的收益主要来自减少中间 tensor、减少 launch 和提高局部性。
最终判断不能只看 microbenchmark。要验证数值一致性、误差容忍、边界 shape、动态 batch、长短序列、异常输入、显存峰值和 p95/p99 延迟;还要检查新 kernel 是否增加维护成本、硬件架构分支和回滚难度。一个成熟答案应说明用 A/B、灰度开关、fallback 和持续 profiling 确保优化收益稳定。
不一定。要看它的端到端占比、是否稳定复现、优化上限、替代方案和维护成本。如果它排第一但只占很小比例,或真正瓶颈在排队、调度、KV 显存上,直接改 kernel 可能收益很小。
如果单个 kernel 内部计算或访存效率低,优先做 kernel 优化;如果多个小算子之间反复读写中间 tensor 或 launch 开销高,融合更可能有效。很多 LLM 推理场景是两者结合,例如 GEMM epilogue 融合 scale、activation 或 dequant。
如果系统在相邻算子之间频繁 transpose、pack/unpack 或处理非连续内存,手写某个 kernel 只能局部加速。统一 layout、对齐访问和减少转换可能直接消掉整段额外开销。
要把优化放回真实模型链路验证,覆盖真实 shape 分布、batch、seq length、prefill/decode、并发和显存压力,并同时看端到端延迟、吞吐、p99 和精度回归。
可能是 kernel launch 开销、同步等待、并行度不足、occupancy 低、寄存器压力、分支发散、小 shape、host-device 往返或框架调度问题,需要继续拆 trace 和 stall 指标。