Prhub

#46508 [Kernel] Enable PDL for per_token_group_quant_8bit_kernel

原始 PR 作者 jeejeelee 合并时间 2026-06-25 08:42 文件变更 1 提交数 4 评论 1 代码增减 +62 / -42

执行摘要

为 per_token_group_quant_8bit_kernel 启用 PDL

PR#42996 引入了 PDL 框架支持,但 per_token_group_quant_8bit_kernel 尚未接入。Review 指出使用原始 asm 缺少 memory clobber,可能导致编译器错误地提前加载输入数据。该 PR 确保该 kernel 正确启用 PDL,消除数据竞争风险。

值得阅读,展示了现代 CUDA 中如何用 PDL 官方 API 替代 asm 实现 grid 同步,是 kernel 开发的良好实践。

讨论亮点

唯一评论来自 mgoin:他指出使用 asm volatile("griddepcontrol.launch_dependents;") 缺少 memory clobber,编译器可以自由地将输入加载提升到 wait 之前,建议改用 cudaGridDependencySynchronize 和 cudaTriggerProgrammaticLaunchCompletion(如 fused_deepseek_v4_qnorm_rope_kv_insert_kernel.cu 中所示)。作者采纳建议,改用官方 API,从而确保插入正确的内存屏障。

实现拆解

  1. 在 kernel 函数 per_token_group_quant_8bit_kernel 开头插入 cudaGridDependencySynchronize(),确保等待前驱 grid 完成后再加载输入数据。
  2. 在量化操作完成后插入 cudaTriggerProgrammaticLaunchCompletion(),宣告本 grid 完成,允许依赖本 grid 的后继 grid 启动。
  3. 将启动宏 LAUNCH_KERNEL 重构为 LAUNCH_KERNEL_INST,使用 cudaLaunchConfig_t 和 cudaLaunchAttribute 设置 programmaticStreamSerializationAllowed=1,替代传统的 <<<>>> 启动方式。
  4. 添加条件编译 #if !defined(USE_ROCM) && (defined(CUDA_ARCH) && CUDA_ARCH >= 900),仅在支持 PDL 的 Hopper 及以上架构上启用,保持向后兼容。
文件 模块 状态 重要度
csrc/libtorch_stable/quantization/w8a8/fp8/per_token_group_quant.cu CUDA 核 modified 4.92

关键符号

per_token_group_quant_8bit_kernel per_token_group_quant_8bit

关键源码片段

csrc/libtorch_stable/quantization/w8a8/fp8/per_token_group_quant.cu core-logic

唯一变更文件,修改了 CUDA kernel 和启动宏以启用 PDL。

// 文件 : csrc/libtorch_stable/quantization/w8a8/fp8/per_token_group_quant.cu
//
// kernel 内部启用 PDL:在加载输入前等待前驱 grid,在量化后通知后继 grid
__global__ void per_token_group_quant_8bit_kernel(/* ... 参数 ... */) {
    // ... 前置计算 (groups_per_block 等 ) ...#if (defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 900))
    // PDL: 等待前驱 grid 完成,确保共享内存或其他依赖已就绪
    cudaGridDependencySynchronize();
#endif    if constexpr (IS_COLUMN_MAJOR) {
        // ... column-major 路径:加载、量化、存储 ...
    } else {
        // ... row-major 路径 ...
    }    // 执行量化核心 ( 向量化加载到 smem 并计算 scale/quant)
    QuantizeGroup<T, DST_DTYPE>(smem_group, group_output, group_size, lane_id,
                                threads_per_group, y_s, min_8bit, max_8bit);#if (defined(__CUDA_ARCH__) && (__CUDA_ARCH__ >= 900))
    // PDL: 标记本 grid 完成,允许依赖本 grid 的后继 grid 启动
    cudaTriggerProgrammaticLaunchCompletion();
#endif
}// 启动 kernel 的辅助宏:使用 cudaLaunchConfig_t + cudaLaunchAttribute
// 启用 programmatic stream serialization 以支持 grid 间依赖
#define LAUNCH_KERNEL_INST(T, DST_DTYPE, COL_MAJOR, UE8M0, SMEM_BYTES) \
    do { \
        cudaLaunchConfig_t config = {}; \
        config.gridDim = dim3(num_blocks); \
        config.blockDim = dim3(num_threads); \
        config.dynamicSmemBytes = (SMEM_BYTES); \
        config.stream = stream; \
        cudaLaunchAttribute attrs[1]; \
        attrs[0].id = cudaLaunchAttributeProgrammaticStreamSerialization; \
        attrs[0].val.programmaticStreamSerializationAllowed = 1; \
        config.attrs = attrs; \
        config.numAttrs = 1; \
        cudaLaunchKernelEx(&config, per_token_group_quant_8bit_kernel<T, DST_DTYPE, \
                           COL_MAJOR, UE8M0>, \
                           input_ptr, output_q_ptr, output_s_ptr, /* ... */); \
    } while(0)

评论区精华

使用官方 PDL API 替代 asm 确保正确性 正确性

mgoin 指出 asm volatile("griddepcontrol.launch_dependents;") 缺少 memory clobber,编译器可自由重排加载指令至 wait 之前。建议改用 cudaGridDependencySynchronize 和 cudaTriggerProgrammaticLaunchCompletion。

结论:作者采纳建议,将 kernel 内的 asm 替换为官方 API,并在启动宏中改用 cudaLaunchAttributeProgrammaticStreamSerialization。 · 已解决

风险与影响

风险较低。条件编译确保低架构版本不启用 PDL,功能不变。唯一可能的风险是 CUDA 驱动版本需支持 cudaGridDependencySynchronize 等新 API(sm90+),但当前代码已用 CUDA_ARCH 保护,编译时不会在低架构上生成此路径。

影响仅限于 per_token_group_quant_8bit_kernel 一个 kernel 函数。调用此 kernel 的 FP8 量化路径(通常用于激活量化)将受益于更安全的 grid 间依赖管理,避免潜在的数据竞争,可能带来轻微的性能提升。对其他路径无影响。

依赖 CUDA sm90+ 无测试覆盖变动

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论