Prhub

#29694 [AMD] Fix int8 per-token quant Triton portability + register test for AMD nightly CI

原始 PR 作者 michaelzhang-ai 合并时间 2026-07-02 03:56 文件变更 2 提交数 4 评论 2 代码增减 +13 / -3

执行摘要

修复 AMD 上 int8 量化 Triton 内核编译错误

AMD ROCm 平台上的 Triton 编译器不再支持 CUDA 特有的 tl.extra.cuda.libdevice.round(对应 __nv_roundf),导致 int8 per-token 量化内核编译时抛出 RuntimeError。本 PR 目标是修复此可移植性问题,并确保 int8 kernel 测试在 AMD nightly CI 中运行。

值得精读。本 PR 展示了如何在不破坏 CUDA 路径的前提下,优雅地解决 Triton 内核在 AMD/ROCm 上的可移植性问题。使用 tl.constexpr 分支消除的模式可复用。

讨论亮点

仅有两个 approval(BBuf 和 HaiShaw),无 review 评论。说明变更过程非常直接,无设计争议。

实现拆解

  1. 修改内核文件 python/sglang/srt/layers/quantization/int8_kernel.py
    • 新增导入 from triton.language.extra import libdeviceis_hip 工具函数。
    • _per_token_quant_int8 内核函数中新增 IS_HIP: tl.constexpr 形参,利用 Triton 的常量编译时分支消除特性。
    • round 调用处,根据 IS_HIP 选择:ROCm 上使用 libdevice.round,CUDA 上保持原有 tl.extra.cuda.libdevice.round,确保 CUDA 路径字节级不变。
    • 在调用处 per_token_quant_int8 中传递 IS_HIP=_is_hip
  2. 注册测试到 AMD nightly CI:在 test/registered/quant/test_int8_kernel.py 中,新增导入 register_amd_ci,并添加 register_amd_ci(est_time=15, suite="nightly-amd-kernel-1-gpu", nightly=True),同时保留原有的 CUDA CI 注册。
文件 模块 状态 重要度
python/sglang/srt/layers/quantization/int8_kernel.py 量化模块 modified 6.45
test/registered/quant/test_int8_kernel.py 测试注册 modified 3.92

关键符号

_per_token_quant_int8 per_token_quant_int8

关键源码片段

python/sglang/srt/layers/quantization/int8_kernel.py dependency-wiring

核心修复文件,修改了 Triton JIT 内核 `_per_token_quant_int8` 的 `round` 调用,新增 `IS_HIP` 分支和 `libdevice` 导入。

# python/sglang/srt/layers/quantization/int8_kernel.py (partial)
import triton
import triton.language as tl
from triton.language.extra import libdevice # 新增:后端无关的 libdevice 模块from sglang.srt.utils import get_device_name, is_cuda, is_hip # 新增 is_hip_is_cuda = is_cuda()
_is_hip = is_hip() # 新增 HIP 检测@triton.jit
def _per_token_quant_int8(
    x_ptr,
    xq_ptr,
    scale_ptr,
    x_sum_ptr,
    stride_x,
    stride_xq,
    N,
    CAL_SUM: tl.constexpr,
    BLOCK: tl.constexpr,
    IS_HIP: tl.constexpr, # 新增:编译时常量,CUDA 上为 False,ROCm 上为 True
):
    row_id = tl.program_id(0)
    cols = tl.arange(0, BLOCK)
    mask = cols < N
​
    x = tl.load(x_ptr + row_id * stride_x + cols, mask=mask, other=0.0).to(tl.float32)
    absmax = tl.maximum(tl.max(tl.abs(x)), 1e-10)
    scale_x = absmax / 127
    x_q = x * (127 / absmax)
    # 根据 IS_HIP 选择 round 实现:
    if IS_HIP:
        # ROCm Triton 已放弃 CUDA 专用 `tl.extra.cuda.libdevice.*` 包装(__nv_roundf),
        # 改用后端无关的 libdevice.round。
        x_q = libdevice.round(x_q).to(tl.int8)
    else:
        # CUDA 路径保持字节级不变,使用原有的 CUDA 内部函数。
        x_q = tl.extra.cuda.libdevice.round(x_q).to(tl.int8)
​
    if CAL_SUM:
        x_sum = tl.sum(x, axis=0)
        tl.store(x_sum_ptr + row_id, x_sum.to(x_sum_ptr.dtype.element_ty))
​
    tl.store(xq_ptr + row_id * stride_xq + cols, x_q, mask=mask)
    tl.store(scale_ptr + row_id, scale_x.to(scale_ptr.dtype.element_ty))
​
​
def per_token_quant_int8(x, scale_dtype=torch.float32, cal_sum=False):
    # ...(省略前面的参数准备代码)
    _per_token_quant_int8[(M,)](
        x, x_q, scales, x_sum,
        stride_x=x.stride(-2),
        stride_xq=x_q.stride(-2),
        N=N,
        CAL_SUM=cal_sum,
        BLOCK=BLOCK,
        IS_HIP=_is_hip, # 传入全局 HIP 标志
        num_warps=num_warps,
        num_stages=1,
    )
    # ...
test/registered/quant/test_int8_kernel.py test-coverage

新增 AMD nightly CI 注册,确保此内核在 AMD 上持续被测试。

# test/registered/quant/test_int8_kernel.py (partial)
from sglang.test.ci.ci_register import register_amd_ci, register_cuda_ci # 新增 register_amd_ci# 保留原有 CUDA CI 注册(base-b 阶段,1-GPU-small 配置)
register_cuda_ci(est_time=15, stage="base-b", runner_config="1-gpu-small")
# 新增 AMD nightly CI 注册(夜间测试套件,1-GPU 配置)
register_amd_ci(est_time=15, suite="nightly-amd-kernel-1-gpu", nightly=True)

评论区精华

没有提炼出高价值讨论线程

当前评论区没有形成足够清晰的争议点或结论,后续有更多讨论时会体现在这里。

风险与影响

低风险。变更高度局部化:仅修改一个 Triton 内核中一个函数的单行代码,且通过 IS_HIP 编译时常量确保 CUDA 路径完全不变。测试注册是增量添加,不影响现有 CUDA CI。唯一潜在风险是 libdevice.round 的行为在 ROCm 上是否与 CUDA 的 round 完全一致,但 PR 作者已在真实 MI350 硬件上验证数值误差小于 3e-3,且与 PyTorch 参考实现一致。

直接影响 AMD GPU(MI350+)用户,使得 int8 MoE 量化路径可以在 ROCm 上正常编译运行。不影响 CUDA、MUSA 等其他后端。测试注册确保 AMD nightly CI 中持续覆盖此功能。

CUDA 路径未经实际测试(但保持字节不变)

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论