真实面经题目 · 原创解析
使用 CUTLASS 优化 GEMM/LLM 推理算子时,通常从 tile 划分、memory hierarchy、epilogue 融合和 Tensor Core 利用率哪些方向入手?
这题考候选人是否能把 CUTLASS 当成可配置的 GEMM/kernel 生成框架来理解:从问题规模、tile 层级、访存搬运、Tensor Core 指令形状、epilogue 融合和 profiling 闭环解释优化,而不是只说“用库会更快”。
真实面经题目 · 原创解析
这题考候选人是否能把 CUTLASS 当成可配置的 GEMM/kernel 生成框架来理解:从问题规模、tile 层级、访存搬运、Tensor Core 指令形状、epilogue 融合和 profiling 闭环解释优化,而不是只说“用库会更快”。
我会先把 CUTLASS 优化说成一套分层选择问题。第一步确认要优化的 GEMM 或 LLM 推理算子形态:M/N/K、batch、prefill 还是 decode、dtype、layout、是否有 bias、activation、dequant、scale、residual 等 epilogue 操作,以及现有 cuBLAS/cuBLASLt 或框架算子的基线。第二步选 tile 层级:threadblock tile 决定一个 CTA 处理多大 M/N/K,warp tile 决定 warp 内如何分工,instruction tile 对应 MMA/Tensor Core 指令形状;tile 太小复用不足,太大可能寄存器、shared memory 压力高、occupancy 下降。第三步看 memory hierarchy:全局内存要合并访问、对齐和减少重复读;shared memory 要做 A/B tile staging、双缓冲或流水线,避免 bank conflict;寄存器里保留 accumulator,提高数据复用。第四步保证 Tensor Core 路径真的被用起来,包括 dtype、对齐、layout、K 维分块和指令 shape 是否匹配。第五步把 LLM 常见的 bias、activation、scale、quant/dequant、残差等尽量放进 epilogue,减少中间 tensor 和额外 kernel launch。最后用 Nsight/NCU 或同类 profiler 看 achieved occupancy、Tensor Core 利用率、DRAM/L2 带宽、shared memory 冲突、stall reason 和端到端收益,并和 cuBLASLt、通用 CUTLASS 配置、手写 kernel 做对比;只有在目标 shape 稳定且收益覆盖维护成本时,才值得继续做专门化。
CUTLASS 不是一句“替换成更快库”就结束。要先明确 GEMM 的 M/N/K、batch、transpose/layout、dtype、对齐、是否小 batch decode、是否有 group GEMM 或 batched GEMM,以及目标指标是单 kernel 延迟、端到端 TTFT、decode 单 token、吞吐还是显存。优化前应和 cuBLAS、cuBLASLt、框架默认实现或已有 kernel 建立可重复基线。
CUTLASS 的优化通常围绕 threadblock shape、warp shape 和 instruction shape 展开。threadblock tile 决定 CTA 级别的数据块和 shared memory 需求,warp tile 决定 warp 内并行分工,instruction tile 对应底层 MMA 指令的矩阵形状。好的 tile 要在数据复用、并行度、寄存器压力、shared memory 占用和 occupancy 之间折中。
GEMM 优化的关键是把全局内存中的 A/B 矩阵 tile 高效搬到 shared memory,再进入寄存器和 MMA 指令。需要关注 global load/store 是否 coalesced、是否向量化和对齐,shared memory staging 是否有双缓冲或流水线,是否出现 bank conflict,以及 accumulator 是否尽量留在寄存器里减少中间写回。
如果目标是 LLM 推理里的 FP16/BF16/INT8 等矩阵乘,回答要说明如何确认 Tensor Core 路径被真正使用:数据类型、矩阵维度对齐、layout、K 维分块、MMA instruction shape 和 pipeline 配置都要匹配。否则代码看似用了 CUTLASS,实际可能没有跑到期望的高吞吐路径。
LLM 算子往往不只是 C = A * B。输出后可能还有 bias、activation、scale、dequant/quant、residual、clamp 或 layout 转换。CUTLASS 的 epilogue 是很重要的工程入口:把这些轻量操作和 GEMM 输出写回融合,减少中间 tensor、显存读写和 kernel launch,通常比单独优化一个小后处理 kernel 更有效。
最终要用 profiler 验证瓶颈:Tensor Core 利用率、SM occupancy、DRAM/L2 带宽、shared memory bank conflict、register spill、stall reason、launch overhead 和不同 shape 的性能分布。若 CUTLASS 专门配置只对极少数 shape 有效,或者已经被 cuBLASLt 覆盖,就要评估是否值得维护多个模板、编译时间、架构分支和 fallback。
因为 GEMM 性能由多层 tile、访存流水线、MMA 指令、寄存器和 shared memory 共同决定。只调 block size 可能提高并行度,却损失复用或造成寄存器溢出,最终不一定更快。
如果问题是标准 GEMM,shape 分布宽,且 cuBLASLt 已有稳定高性能算法和 epilogue 支持,优先用成熟库。CUTLASS 更适合需要特殊融合、特殊 layout、固定热点 shape 或库路径覆盖不足的场景。
主要是减少 GEMM 输出写回后再被小 kernel 读取的显存往返,同时减少 kernel launch 和同步开销。对于 bandwidth-bound 的后处理链路,融合常能带来端到端收益。
可以看 profiler 里的 Tensor Core/MMA 指令利用、SM 吞吐、stall reason、memory throughput 和实际 FLOPS。如果算子更多受访存、同步或 fallback 指令限制,Tensor Core 峰值不会体现出来。
不完全一样。prefill 大 GEMM 更容易形成高计算密度,decode 小 batch 可能更受权重带宽、launch 开销和 shape 不规则影响,tile、split-K、persistent 策略和融合收益都要分别测。