真实面经题目 · 原创解析
LLM 推理算子变慢时,如何判断瓶颈是 Memory Bound 还是 Compute Bound?
这题考算子性能诊断方法。回答要从理论 roofline、算术强度、实际 profiler 指标、stall reason 和优化方向闭环判断,而不是只说“看 GPU 利用率”。
真实面经题目 · 原创解析
这题考算子性能诊断方法。回答要从理论 roofline、算术强度、实际 profiler 指标、stall reason 和优化方向闭环判断,而不是只说“看 GPU 利用率”。
我会先用 roofline 思路做第一层判断:估计算子的 FLOPs 和实际搬运字节数,得到 arithmetic intensity,也就是每搬运 1 byte 做多少计算。如果算术强度低,理论上更容易 Memory Bound;如果算术强度高并接近硬件计算峰值,更可能 Compute Bound。第二层用 profiler 验证:看 achieved FLOPS、DRAM/L2 带宽利用率、SM active、Tensor Core 利用率、warp stall reason、memory transaction、cache hit、occupancy 和指令吞吐。如果带宽接近上限、SM 经常等内存、提高计算并行度收益不大,偏 Memory Bound;如果带宽不高但计算单元接近满载、指令吞吐或 Tensor Core 利用率是瓶颈,偏 Compute Bound。第三层用优化实验确认:Memory Bound 优先减少访存、提高复用、融合算子、改善 coalescing 和 cache;Compute Bound 优先用 Tensor Core、改 tile、提高并行度、减少指令和分支。真正工程上还要注意很多算子是混合瓶颈,batch size、sequence length、数据类型和布局变化会改变结论。
Roofline 模型把性能上限拆成内存带宽上限和计算峰值上限。先估算算子需要多少 FLOPs、读写多少字节,再计算 arithmetic intensity。低算术强度通常说明每做一点计算就要搬很多数据,更可能被内存带宽限制;高算术强度才有机会逼近计算峰值。
Memory Bound 时,DRAM 或 L2 带宽利用率高,warp stall 多来自 memory dependency、long scoreboard 或 memory throttle,SM 计算单元不一定忙。优化计算指令通常收益小,但减少读写、改善 coalescing、增加数据复用或融合 kernel 会带来明显收益。
Compute Bound 时,计算单元、Tensor Core 或 FP/INT pipeline 接近饱和,achieved FLOPS 接近该数据类型和硬件路径的可达上限,内存带宽未满。此时瓶颈可能来自 tile 设计、指令调度、寄存器复用、warp 分配、分支或没有用上合适的矩阵计算单元。
线性层大 GEMM 往往更可能 Compute Bound 或受 Tensor Core 喂数影响;小 batch decode、KV cache 读写、norm、sampling、dequant 和部分 attention 阶段更容易 Memory Bound。Prefill 和 decode 的输入形态不同,同一个算子在不同 batch、seq length 下也可能切换瓶颈。
判断不能只靠一个指标。可以做控制实验:减少数据量、改 layout、融合访存、增加 tile 复用,如果性能明显改善,说明内存路径关键;换用 Tensor Core、调整 tile shape、减少指令或提高 occupancy,如果性能改善,说明计算或执行调度关键。实验要和 profiler 指标互相印证。
Memory Bound 的方向是少搬、顺序搬、复用搬来的数据,例如算子融合、cache/blocking、向量化、coalescing、压缩或更低精度存储。Compute Bound 的方向是更快算、更并行算,例如 Tensor Core、合适精度、tile shape、unroll、减少分支和提高指令吞吐。瓶颈判断错会把优化做反。
不能。GPU 利用率太粗,可能计算忙、内存忙、等待同步或 launch 很多小 kernel。要看带宽、FLOPS、stall reason 和具体算子时间。
用算子总 FLOPs 除以从内存读写的字节数。估算时要考虑真实读写、重复访问、cache 复用和中间结果写回,不能只看输入输出 tensor 大小。
Decode 常是小 batch、逐 token 生成,计算规模相对小,同时要频繁读 KV cache。每个 token 的访存压力高,算术强度可能低于 prefill 的大矩阵计算。
可能是 occupancy 低、kernel launch 开销、同步等待、分支发散、依赖链、寄存器压力、访存不合并或小 shape 下并行度不足。需要继续看 profiler 的 stall 和调度指标。