Prhub

#50243 [Build] Fix CUDA release wheel builds

原始 PR 作者 khluu 合并时间 2026-07-31 02:48 文件变更 3 提交数 3 评论 2 代码增减 +90 / -50

执行摘要

修复 CUDA release wheel 构建中的 NCCL 依赖与 BF16 编译失败

PR body 指出:CUDA 12.9 release 作业因为 DeepEP 依赖 NCCL 2.30.4+ 而失败,同时 Kimi K3 的 BF16 转换在 CUDA 13 x86 编译 SM75 时因缺少特化而失败。需要修复这些构建错误以产出可用的 wheel 包。

此 PR 是典型的构建修复,值得略读以了解 CUDA 构建兼容性处理方式。Kimi K3 相关开发者需注意 SM 守卫逻辑,避免后续添加新功能时遗漏类似条件。

讨论亮点

无 review 评论,两位 reviewer(Harry-Chen 和 mgoin)直接批准。之前合并的 PR #50357 为此 PR 奠定了基础(mgoin 提到 restart 后 CI 通过)。

实现拆解

  1. NCCL 版本固定(Dockerfile):将 NCCL 版本覆盖条件从 CUDA_MAJOR >= 13 改为 -n $NCCL_VERSION,使得 CUDA 12 下也能使用 UV_OVERRIDE 强制安装 NCCL 2.30.7。修改了 Dockerfile 中 DeepEP 安装步骤和运行时镜像两个位置。
  2. Kimi K3 BF16 编译守卫(CUDA 内核):在 csrc/libtorch_stable/fused_kimi_k3_mla_key_concat_kv_cache_kernel.cu 的 copyChunk8 模板函数中,添加预处理器指令 #if (!defined(__CUDA_ARCH__) || __CUDA_ARCH__ < 800) && !defined(USE_ROCM),在其分支内用 if constexpr (std::is_same_v<scalar_t, c10::BFloat16>) 提前 return,避免编译 _typeConvert<BFloat16> 特化。同时对 FP8 路径也包裹在 #endif 之后,确保逻辑完整性。
  3. 文档图更新:dockerfile-stages-dependency.png 更新以反映 Dockerfile 的 stage 变化。
文件 模块 状态 重要度
csrc/libtorch_stable/fused_kimi_k3_mla_key_concat_kv_cache_kernel.cu CUDA 内核 modified 4.99
docker/Dockerfile 部署脚本 modified 3.8
docs/assets/contributing/dockerfile-stages-dependency.png 文档 modified 1.53

关键符号

copyChunk8

关键源码片段

csrc/libtorch_stable/fused_kimi_k3_mla_key_concat_kv_cache_kernel.cu core-logic

核心变更:添加 BF16 编译守卫,防止在 pre-Ampere 上编译错误

// 文件 : csrc/libtorch_stable/fused_kimi_k3_mla_key_concat_kv_cache_kernel.cu
// copyChunk8: 当 FP8 或 APPLY_ROPE 时减少共享内存读取。
// 修改 : 为 BFloat16 添加编译时守卫,避免在 SM<80 上编译 _typeConvert 特化。
__device__ __forceinline__ void copyChunk8(
    void* dst, const scalar_t* src, const float* cos_sin,
    int rope_elem_base = 0) {
  uint4 const v = *reinterpret_cast<const uint4*>(src);
  if constexpr (FP8 || APPLY_ROPE) {
#if (!defined(__CUDA_ARCH__) || __CUDA_ARCH__ < 800) && !defined(USE_ROCM)
    // CUDA host 或 pre-Ampere 设备上 _typeConvert<BFloat16> 不可用。
    // Kimi K3 使用 bf16 输入,因此在此类构建中直接返回,避免编译错误。
    if constexpr (std::is_same_v<scalar_t, c10::BFloat16>) {
      return;
    } else {
#endif
      using Converter = vllm::_typeConvert<scalar_t>;
      auto const* p = reinterpret_cast<typename Converter::packed_hip_type const*>(&v);
      float f[kVecElems];
#pragma unroll
      for (int i = 0; i < 4; i++) {
        float2 x = Converter::convert(p[i]);
        f[2 * i] = x.x;
        f[2 * i + 1] = x.y;
      }
      // ... ( 剩余 rope 应用和 fp8 转换 )
#if (!defined(__CUDA_ARCH__) || __CUDA_ARCH__ < 800) && !defined(USE_ROCM)
    }
#endif
  }
}
docker/Dockerfile infrastructure

修改 NCCL 版本覆盖条件,使其适用于所有 CUDA 版本(原来仅 CUDA 13+),确保 DeepEP 能获得正确 NCCL。

# 文件 : docker/Dockerfile
# 修改 NCCL 版本覆盖条件,使得 CUDA 12 也能强制使用 NCCL 2.30.7
​
# 在 DeepEP 构建阶段 :
# 原 : if [ "$CUDA_MAJOR" -ge 13 ] && [ -n "$NCCL_VERSION" ]; then
# 新 : 移除 CUDA 版本判断,只要 NCCL_VERSION 设置就执行
RUN --mount=type=cache,target=/opt/uv/cache \
    mkdir -p /tmp/ep_kernels_workspace/dist && \
    CUDA_MAJOR=$(echo $CUDA_VERSION | cut -d. -f1) && \
    if [ -n "$NCCL_VERSION" ]; then \
      echo "nvidia-nccl-cu${CUDA_MAJOR}==${NCCL_VERSION}" \
        > /tmp/nccl-override.txt && \
      export UV_OVERRIDE=/tmp/nccl-override.txt; \
    fi && \
    ...
​
# 在运行时镜像阶段也做相同修改 :
RUN CUDA_MAJOR=$(echo $CUDA_VERSION | cut -d. -f1) && \
    if [ -n "$NCCL_VERSION" ]; then \
      echo "nvidia-nccl-cu${CUDA_MAJOR}==${NCCL_VERSION}" \
        > /etc/uv-overrides.txt; \
    else \
      > /etc/uv-overrides.txt; \
    fi

评论区精华

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

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

风险与影响

风险较低,变更集中在构建配置和编译守卫,不影响运行时逻辑。潜在风险:

1) NCCL 版本强制覆盖可能与其他依赖冲突,但 2.30.7 是经测试的兼容版本;
2) BF16 守卫在 SM<80 时直接 return,可能导致内核静默不执行,但 Kimi K3 模型本身不会运行在这些 GPU 上。

直接影响通过 release-v2 构建的 CUDA wheel 包(CUDA 12 和 CUDA 13),确保构建成功。对用户无运行时影响,但修复了之前构建失败导致无包可用的状态。Kimi K3 在 pre-Ampere GPU 上不可用(编译时即拒绝),但这不是预期使用场景。

编译守卫可能隐藏错误 NCCL 版本覆盖影响范围扩大

关联 Issue

#50000 [New model] Kimi K3

完整报告

参与讨论