真实面经题目 · 原创解析

使用 CUTLASS 优化 GEMM/LLM 推理算子时,通常从 tile 划分、memory hierarchy、epilogue 融合和 Tensor Core 利用率哪些方向入手?

这题考候选人是否能把 CUTLASS 当成可配置的 GEMM/kernel 生成框架来理解:从问题规模、tile 层级、访存搬运、Tensor Core 指令形状、epilogue 融合和 profiling 闭环解释优化,而不是只说“用库会更快”。

出现于:快手 · C/C++

60 秒回答模板

我会先把 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 稳定且收益覆盖维护成本时,才值得继续做专门化。

考点 从 shape 和基线开始
难度 真实面经题
回答目标 让候选人能把 CUTLASS 优化讲成可验证的工程流程:先定 shape 和基线,再从 tile、访存、Tensor Core、epilogue 融合和 profiling 闭环推导方案。

深入解析

01

先定义算子形态和基线

CUTLASS 不是一句“替换成更快库”就结束。要先明确 GEMM 的 M/N/K、batch、transpose/layout、dtype、对齐、是否小 batch decode、是否有 group GEMM 或 batched GEMM,以及目标指标是单 kernel 延迟、端到端 TTFT、decode 单 token、吞吐还是显存。优化前应和 cuBLAS、cuBLASLt、框架默认实现或已有 kernel 建立可重复基线。

02

tile 层级是核心旋钮

CUTLASS 的优化通常围绕 threadblock shape、warp shape 和 instruction shape 展开。threadblock tile 决定 CTA 级别的数据块和 shared memory 需求,warp tile 决定 warp 内并行分工,instruction tile 对应底层 MMA 指令的矩阵形状。好的 tile 要在数据复用、并行度、寄存器压力、shared memory 占用和 occupancy 之间折中。

03

memory hierarchy 决定带宽效率

GEMM 优化的关键是把全局内存中的 A/B 矩阵 tile 高效搬到 shared memory,再进入寄存器和 MMA 指令。需要关注 global load/store 是否 coalesced、是否向量化和对齐,shared memory staging 是否有双缓冲或流水线,是否出现 bank conflict,以及 accumulator 是否尽量留在寄存器里减少中间写回。

04

Tensor Core 利用率要落到指令路径

如果目标是 LLM 推理里的 FP16/BF16/INT8 等矩阵乘,回答要说明如何确认 Tensor Core 路径被真正使用:数据类型、矩阵维度对齐、layout、K 维分块、MMA instruction shape 和 pipeline 配置都要匹配。否则代码看似用了 CUTLASS,实际可能没有跑到期望的高吞吐路径。

05

epilogue 融合能减少跨算子浪费

LLM 算子往往不只是 C = A * B。输出后可能还有 bias、activation、scale、dequant/quant、residual、clamp 或 layout 转换。CUTLASS 的 epilogue 是很重要的工程入口:把这些轻量操作和 GEMM 输出写回融合,减少中间 tensor、显存读写和 kernel launch,通常比单独优化一个小后处理 kernel 更有效。

06

profile 和维护边界决定是否继续

最终要用 profiler 验证瓶颈:Tensor Core 利用率、SM occupancy、DRAM/L2 带宽、shared memory bank conflict、register spill、stall reason、launch overhead 和不同 shape 的性能分布。若 CUTLASS 专门配置只对极少数 shape 有效,或者已经被 cuBLASLt 覆盖,就要评估是否值得维护多个模板、编译时间、架构分支和 fallback。

易错点

  • 把 CUTLASS 答成一个黑盒库名,只说“调用 CUTLASS 比手写快”,没有解释 tile、访存和 epilogue。
  • 只追求更大的 tile,没有讨论寄存器压力、shared memory 占用、occupancy 和 spill 风险。
  • 默认用了 CUTLASS 就一定用了 Tensor Core,没有检查 dtype、layout、对齐和 MMA 指令路径。
  • 只看单 kernel microbenchmark,不看 LLM 链路里的 prefill/decode shape 分布和端到端收益。
  • 忽略 cuBLASLt、框架算子和手写 kernel 的取舍,把所有 GEMM 都强行专门化。
  • 把通用 CUTLASS 优化知识说成快手内部实现或面试追问细节;来源只支持“介绍 Cutlass 优化思路”这一题面。

面试官追问

CUTLASS 优化为什么不能只调一个 block size?

因为 GEMM 性能由多层 tile、访存流水线、MMA 指令、寄存器和 shared memory 共同决定。只调 block size 可能提高并行度,却损失复用或造成寄存器溢出,最终不一定更快。

什么时候优先用 cuBLASLt,而不是自己配 CUTLASS?

如果问题是标准 GEMM,shape 分布宽,且 cuBLASLt 已有稳定高性能算法和 epilogue 支持,优先用成熟库。CUTLASS 更适合需要特殊融合、特殊 layout、固定热点 shape 或库路径覆盖不足的场景。

epilogue 融合的主要收益是什么?

主要是减少 GEMM 输出写回后再被小 kernel 读取的显存往返,同时减少 kernel launch 和同步开销。对于 bandwidth-bound 的后处理链路,融合常能带来端到端收益。

如何判断 CUTLASS kernel 没有跑满 Tensor Core?

可以看 profiler 里的 Tensor Core/MMA 指令利用、SM 吞吐、stall reason、memory throughput 和实际 FLOPS。如果算子更多受访存、同步或 fallback 指令限制,Tensor Core 峰值不会体现出来。

decode 小 batch GEMM 和 prefill 大 GEMM 的优化重点一样吗?

不完全一样。prefill 大 GEMM 更容易形成高计算密度,decode 小 batch 可能更受权重带宽、launch 开销和 shape 不规则影响,tile、split-K、persistent 策略和融合收益都要分别测。