Prhub

#51507 [Perf] Launch the top-k/top-p Triton sampler kernel with 8 warps

原始 PR 作者 BabyDrangoner 合并时间 2026-08-11 01:55 文件变更 1 提交数 4 评论 13 代码增减 +7 / -0

执行摘要

采样 Triton kernel 改 8 warps 启动,多架构提速最高 1.85×

PR body 说明 _topk_topp_kernel(来自 #42191 的 Qrita 采样 kernel)每个 program 只处理一行 logits,并串行以 BLOCK_SIZE=8192 的 tile 扫完整行,因此 per-tile 延迟直接决定 kernel 延迟;Triton 默认 4 warps 让每个 lane 处理 16 个元素,吞吐被 warp 饥饿卡住。该 kernel 位于 seeded / per-request-generator 采样热路径(FlashInfer 拒绝 per-request generator),在 Qwen3.6-35B-A3B-FP8 batch-16 decode 上是单步最大的非 GEMM kernel,所以仅调整 warp 数就能直接转化为端到端解码提速。

代码本身只有 7 行,真正值得精读的是 review 中的跨架构 benchmark 方法论:作者与 reviewer 分别覆盖 SM120、H200、MI350X,并围绕 nw8 vs nw16 做了完整的数值等价性与性能取舍验证。若关心 Triton kernel launch 调优、采样器热路径优化或 arch-conditional 参数决策,可重点读本 PR 的讨论与提交演进;普通业务使用者无需深读。

讨论亮点

核心交锋:

  • cakeng 在 H200 与 MI350X 上做了补充 sweep,发现 MI350X 上 nw8 多数胜出、H200 上 nw16 胜点更多,建议在 B200 上验证并考虑 arch-conditional 参数。
  • BabyDrangoner 在 SM120(RTX PRO 6000)全 96 场景 sweep 得到 nw8=63 / nw16=32 / nw4=1,并按同样口径重算 H200 为 nw8=68 / nw16=27,论证 8 warps 是两台机器上的多数最优。
  • cakeng 好奇 nw16 胜点为何集中在 top-p-only 小 batch 与 mixed_partial 大 batch;作者解释 top-p 路径的 pivot 搜索每次迭代都重新计算 exp(logits - max),充满 tl.exp,更多 warps 能隐藏 SFU 延迟,而 32 warps 因寄存器压力全输。
  • njhill 在 MI355X 验证后直接移除平台判断,并确认先统一用 8、后续再单独精调。

实现拆解

  1. 变更入口在 vllm/v1/sample/ops/topk_topp_triton.pyapply_top_k_top_p_triton:新增 launch_kwargs = {},用于向 Triton kernel 透传 launch 参数。
  2. 设备分支保持不变:CPU 用 block_size=256, block_size_trunc=128,XPU 用 4096 / 2048,其余 GPU 用 8192 / 4096;在 GPU 分支内设置 launch_kwargs['num_warps'] = 8
  3. kernel 调用追加 **launch_kwargs_topk_topp_kernel 因此以 8 warps 启动;BLOCK_SIZE 维持 8192 不变(4k / 8k / 16k sweep 确认它仍是最优 tile)。
  4. 平台取舍:最初只对 CUDA 开启,njhill 在 MI355X(gfx950)上实测 84 / 84 场景 8 warps 更快(平均 1.12×)后移除 ROCm 排除,GPU 统一 8 warps;CPU / XPU 不受影响。
  5. 验证与配套:作者使用 pytest tests/v1/sample/test_topk_topp_sampler.py,SM120 上 129 passed / 2 skipped,H20 上 135 passed / 2 skipped;未新增测试文件或配置改动。
文件 模块 状态 重要度
vllm/v1/sample/ops/topk_topp_triton.py 采样器 modified 4.19

关键符号

apply_top_k_top_p_triton

关键源码片段

vllm/v1/sample/ops/topk_topp_triton.py performance-tuning

唯一变更文件:在 `apply_top_k_top_p_triton` 中通过 `launch_kwargs` 把 `_topk_topp_kernel` 的 Triton 启动 warp 数从默认 4 改为 8,直接改善串行扫描整行 vocab 时的 per-tile 延迟;+7 / -0。

# vllm/v1/sample/ops/topk_topp_triton.py(节选)# _topk_topp_kernel 每个 program 串行 sweep 整行 vocab,因此 per-tile 延迟直接
# 决定 kernel 延迟;默认 4 warps 时 8192 宽的 tile 有 16 个元素 / lane,warp 饥饿。
def apply_top_k_top_p_triton(...):
    ...
    launch_kwargs = {}
​
    if logits.device.type == 'cpu':
        # CPU 上更小的 tile 编译、运行更快。
        block_size, block_size_trunc = 256, 128
    elif logits.device.type == 'xpu':
        # XPU 上大 tile 会在单遍 pivot 近似中损失精度,因此用小 tile。
        block_size, block_size_trunc = 4096, 2048
    else:
        # GPU 上 8192 是 4k / 8k / 16k sweep 验证过的最优 tile 大小。
        block_size, block_size_trunc = 8192, 4096
        # 8 warps 把每 lane 元素数降到 8,在 SM90 / SM100 / SM120 / gfx950 上
        # 全面快于 4;16 warps 因寄存器压力无法稳定收益,故不采用。
        launch_kwargs['num_warps'] = 8
​
    _topk_topp_kernel[(NUM_PROGRAMS,)](
        logits,
        # ... 其余 logits / k / p 等参数照旧传入
        BLOCK_SIZE_TRUNC=block_size_trunc,
        TOPK_ENABLED=topk_enabled,
        TOPP_ENABLED=topp_enabled,
        **launch_kwargs,
    )
    return logits

评论区精华

8 warps vs 16 warps 的跨架构取舍 性能

cakeng 在 H200 / MI350X 上 sweep 发现 nw8 多数胜出,但 H200 上 nw16 胜点更多,建议在 B200 上验证并考虑 arch-conditional;BabyDrangoner 在 SM120 全 96 场景 sweep 得到 nw8=63 / nw16=32 / nw4=1,并重算 H200 tally 也是 nw8 多数胜。

结论:统一先取 8 warps 作为普适、保守的最优值,后续再按 workload 或架构精调。 · 已解决

16 warps 在 top-p-only / mixed-partial 场景胜出的原因 设计

cakeng 好奇 nw16 胜点集中在 top-p-only 小 batch 和 mixed_partial 大 batch;作者提出 top-p 路径的 pivot 搜索充满 tl.exp,更多 warps 能隐藏 SFU 延迟,而 32 warps 因寄存器压力全输。

结论:作为 follow-up 观察,不阻塞本 PR;作者指出更干净的长期优化是减少 top-p 搜索中的 exp 重算(#48927 的 log-space pivot search)。 · 待处理

是否保留平台判断(CUDA-only) 设计

njhill 在 MI355X 上测得 ROCm 同样 8 warps 全面更优(84 / 84,平均 1.12×),因此移除平台排除;cakeng 认可该决策。

结论:去掉 arch-conditional 判断,GPU 统一 8 warps;CPU / XPU 分支不进入。 · 已解决

风险与影响

  1. B200 / SM100 没有实测数据列。8-vs-4 方向在所有已测架构一致,但 8-vs-16 在 top-p-only 场景仍有几个百分点差距,统一取 8 warps 可能不是极端最优,后续可做 arch-conditional 或 workload-specific 精调。
  2. 纯 top-p 在 pivot 边界有极少量 token 翻转(SM120 2/36,H20 最坏 28 tokens),但相对 fp64 参考,8 warps 与 4 warps 的 kept-mass 距离同为约 1e-5,不构成新增精度回归。
  3. 没有新增自动化测试锁定 num_warps=8 的行为;现有 sampler 测试覆盖了结果一致性,但没有专门覆盖不同 warp 数组合。
  4. CPU / XPU 分支不进入 GPU 分支,因此不受影响,但未来若调整设备分支结构需要留意不要误伤。

对用户:seeded / per-request-generator 采样路径的吞吐提升明显,Qwen3.6-35B-A3B-FP8 batch-16 decode 场景下 _topk_topp_kernel 从 305.8 µs/step 降到 165.9 µs/step(1.84×);无 API、配置或依赖变化,top-k 相关输出与 4 warps 逐位一致。对系统:只改 Triton kernel 的 launch 配置,不影响调度、KV cache 或模型权重路径。对团队:提供了一个跨架构 kernel launch 调优的方法论案例,也为后续 top-p 搜索算法优化(减少 exp 重算)建立了基线。

采样热路径变更 B200 未实测 top-p 存在极少量 pivot 边界浮点翻转 无新增测试

关联 Issue

未识别关联 Issue

当前没有检测到明确关联的 Issue 链接,后续同步到相关引用后会出现在这里。

完整报告

参与讨论