Prhub

#45176 [11a/n] Migrate Marlin kernels to torch stable ABI

原始 PR 作者 cleonard530 合并时间 2026-06-12 12:22 文件变更 19 提交数 11 评论 14 代码增减 +627 / -573

执行摘要

Marlin 内核迁移至 stable ABI

继续 libtorch stable ABI 迁移(见 #26946),消除 Marlin 内核与不稳定 PyTorch ABI 的耦合,降低未来版本升级的兼容性风险。

值得精读,特别是 marlin_int4_fp8_preprocess.cu 中的 stream 修复示例,展示迁移过程中的正确性改进;torch_bindings.cpp 的算子注册模式可作其他内核迁移参考。

讨论亮点

主要讨论集中在:

  • Stream 修复:janeyx99 询问 stream 添加原因,cleonard530 解释为避免竞争条件并更新了描述。
  • 死代码移除:janeyx99 指出 marlin.cu 中残留不稳定头文件和死代码,已移除。
  • CMakeLists 条件:janeyx99 询问 MARLIN_OTHER_ARCHS 是否新增,作者说明是原条件迁移。
  • awq_repack 检查顺序:janeyx99 注意到检查在输出分配前进行,但未要求修改。

实现拆解

实现步骤包括:

  1. 文件搬迁:将 csrc/quantization/marlin/ 下的所有源文件、头文件和生成脚本移至 csrc/libtorch_stable/quantization/marlin/
  2. API 替换:将所有 torch::Tensor 替换为 torch::stable::TensorTORCH_CHECK 替换为 STD_TORCH_CHECK,并改用 stable 头文件。
  3. 算子注册切换:在 csrc/libtorch_stable/torch_bindings.cpp 通过 STABLE_TORCH_LIBRARY_FRAGMENT 添加 marlin_gemmgptq_marlin_repackawq_marlin_repackmarlin_int4_fp8_preprocess 算子定义;在 csrc/torch_bindings.cpp 中删除对应定义。
  4. Stream 修复:在 marlin_int4_fp8_preprocess.cu 中,使用 get_current_cuda_stream() 获取当前 PyTorch stream 而非默认 stream。
  5. 构建适配:更新 CMakeLists.txt,将新路径源文件加入 _C_stable_libtorch 目标。
  6. 测试验证:通过 tests/models/quantization/test_gptq_marlin.py 确认功能正确。
文件 模块 状态 重要度
csrc/libtorch_stable/quantization/marlin/marlin.cu Marlin 内核 renamed 6.6
csrc/libtorch_stable/torch_bindings.cpp 算子注册 modified 6.21
csrc/torch_bindings.cpp 算子注册 modified 5.92
csrc/libtorch_stable/quantization/marlin/marlin_int4_fp8_preprocess.cu Marlin 内核 added 6.05
csrc/libtorch_stable/quantization/marlin/gptq_marlin_repack.cu Marlin 内核 renamed 5.68
CMakeLists.txt 构建系统 modified 4.8

关键符号

marlin_gemm gptq_marlin_repack awq_marlin_repack marlin_int4_fp8_preprocess

关键源码片段

csrc/libtorch_stable/torch_bindings.cpp core-logic

在 stable libtorch 扩展中注册 Marlin 算子。

// csrc/libtorch_stable/torch_bindings.cpp
// 在 stable libtorch 扩展中注册 Marlin 算子STABLE_TORCH_LIBRARY_FRAGMENT(_C, ops) {
  // ... 其他已有注册 ...  // Marlin GEMM 主算子
  ops.def(
      "marlin_gemm(Tensor a, Tensor? c_or_none, Tensor b_q_weight, "
      "Tensor? b_bias_or_none,Tensor b_scales, "
      "Tensor? a_scales, Tensor? global_scale, Tensor? b_zeros_or_none, "
      "Tensor? g_idx_or_none, Tensor? perm_or_none, Tensor workspace, "
      "int b_type_id, SymInt size_m, SymInt size_n, SymInt size_k, "
      "bool is_k_full, bool use_atomic_add, bool use_fp32_reduce, "
      "bool is_zp_float) -> Tensor");  // GPTQ 权重重排
  ops.def(
      "gptq_marlin_repack(Tensor b_q_weight, Tensor perm, "
      "SymInt size_k, SymInt size_n, int num_bits, bool is_a_8bit) -> Tensor");  // AWQ 权重重排
  ops.def(
      "awq_marlin_repack(Tensor b_q_weight, SymInt size_k, "
      "SymInt size_n, int num_bits, bool is_a_8bit) -> Tensor");  // int4 到 fp8 的预处理
  ops.def(
      "marlin_int4_fp8_preprocess(Tensor qweight, "
      "Tensor? qzeros_or_none, bool inplace) -> Tensor");
}
csrc/libtorch_stable/quantization/marlin/marlin_int4_fp8_preprocess.cu core-logic

新增的 stable ABI 内核文件,包含 stream 修复。

// csrc/libtorch_stable/quantization/marlin/marlin_int4_fp8_preprocess.cu
// 使用 torch stable ABI 重写的 int4 -> fp8 预处理函数。
// 关键改进:通过 get_current_cuda_stream 获取当前 stream,避免竞态条件。#include "marlin.cuh"
#include <torch/csrc/stable/accelerator.h>
#include <torch/csrc/stable/library.h>
// ... 其他 includetorch::stable::Tensor marlin_int4_fp8_preprocess(
    torch::stable::Tensor& qweight,
    std::optional<torch::stable::Tensor> qzeros_or_none,
    bool inplace) {
  // 使用 stable 宏检查输入
  STD_TORCH_CHECK(qweight.is_cuda(), "qweight is not on GPU");
  STD_TORCH_CHECK(qweight.scalar_type() == torch::headeronly::ScalarType::Int,
                  "qweight.dtype != torch.int32");  const int32_t device_index = qweight.get_device_index();
  torch::stable::accelerator::DeviceGuard device_guard(device_index);
  // 获取当前 CUDA stream,而非默认 stream
  const cudaStream_t stream = get_current_cuda_stream(device_index);  torch::stable::Tensor output =
      inplace ? qweight : torch::stable::empty_like(qweight);  if (!qzeros_or_none.has_value()) {
    // 处理无零点 (non-zp) 格式
    int blocks = qweight.numel() * 8 / 256;
    marlin_int4_fp8_preprocess_kernel_without_zp<<<blocks, 32, 0, stream>>>(
        reinterpret_cast<const int32_t*>(qweight.const_data_ptr()),
        reinterpret_cast<int32_t*>(output.mutable_data_ptr()));
  } else {
    // 处理 AWQ 格式(略)
  }
  return output;
}

评论区精华

marlin_int4_fp8_preprocess CUDA stream 修复 正确性

janeyx99 询问添加 stream 获取的原因,并指出之前使用默认 stream 可能不安全。

结论:cleonard530 确认这是有意改进,避免竞态条件,并更新了 PR 描述。 · 已解决

移除不稳定头文件和死代码 cleanup

janeyx99 指出 marlin.cu 包含了 non-stable 头文件 core/registration.h 以及一条死代码。

结论:cleonard530 随后将其移除。 · 已解决

CMakeLists 中 MARLIN_OTHER_ARCHS 条件 question

janeyx99 询问 CMakeLists.txt 中 `if (MARLIN_OTHER_ARCHS)` 条件是否新加。

结论:cleonard530 解释该条件并非新加,只是从旧位置移过来,且应与 Marlin 相关选项保持在一起。 · 已解决

awq_marlin_repack 检查顺序变化 正确性

janeyx99 注意到参数检查在输出分配之前进行,认为这可能更正确,标记为差异。

结论:作者未作修改,但留下记录。该变化疑似更正确,但无直接影响。 · 已解决

风险与影响

风险较低:迁移为等价替换,接口语义不变,通过现有测试。主要风险是构建配置遗漏,但 review 已确认 CMake 修改。stream 修复本身降低了潜在并发风险。

对用户:无功能变化,接口完全一致。对系统:消除不稳定 ABI 依赖,提升 PyTorch 升级兼容性。对团队:推进 stable ABI 迁移进度,为移除 legacy _C 铺路。

稳定 ABI 迁移 低回归风险

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论