SGLang 中 AMD GPU 内核源文件后缀分析:.cu vs .hip

结论速览

  • 当前并未把 AMD GPU 代码"统一"改成 .cu 后缀。
  • 仓库里同时存在 .cu(CUDA 源文件,ROCm 构建时由 hipify 自动转换)和 .hip(原生 HIP 实现或 hipify 产物)两种后缀。
  • .hip 文件数量很少(git 跟踪的仅 7 个),绝大多数 GPU 代码仍以 .cu 形式维护 ,ROCm 构建通过 PyTorch hipify / CMake LANGUAGE HIP 机制把 .cu 编译到 HIP。
  • 因此"以前用 .hip"的直观感受部分正确:早期的 custom_all_reduce 等确实有独立 .hip 文件,但后来新增功能走的是"写 .cu + 构建期 hipify"或"少数核心算子单独写 .hip"的混合路线。

1. 当前代码库中的 .cu 与 .hip 分布

1.1 在 python/sglang/kernels/aot/csrc/(AOT sgl-kernel / sglang-kernel wheel 源码)

复制代码
$ git ls-files 'python/sglang/kernels/aot/csrc/*.hip' 'python/sglang/kernels/aot/csrc/**/*.hip'
python/sglang/kernels/aot/csrc/allreduce/custom_all_reduce.hip
python/sglang/kernels/aot/csrc/allreduce/deterministic_all_reduce.hip
python/sglang/kernels/aot/csrc/elementwise/topk.hip
  • 只有 3 个 .hip 文件被 Git 跟踪。
  • 其余大量算子(activation、attention、gemm、moe、quantization、grammar、kvcache、spatial 等)全部以 .cu 形式存在。

1.2 在 python/sglang/kernels/ops/(按算子组组织的 Python facade)

复制代码
$ git ls-files '*.hip'
...
python/sglang/kernels/ops/gemm/smallm_fp8_blockscale_gfx950/smallm_fp8_blockscale_gemm.hip
python/sglang/kernels/ops/gemm/smallm_fp8_gfx950/smallm_fp8_gemm.hip
python/sglang/kernels/ops/moe/smallm_moe_gfx950/smallm_moe.hip
python/sglang/kernels/ops/moe/smallm_router_gfx950/smallm_router.hip
  • 这些是 gfx950(MI350/MI355 系列)专用的小型矩阵/ MoE kernel,属于 AMD 针对新架构手工优化的原生 HIP 代码。

2. ROCm 构建系统如何使用后缀

2.1 两个并行的 ROCm 构建入口

入口 位置 构建方式 后缀处理
scikit-build-core + CMake 3rdparty/amd/wheel/sgl-kernel/CMakeLists_rocm.txt build_rocm.sh 把它重命名为 CMakeLists.txt 后用 uv build 显式列出 .hip 源文件,并 set_source_files_properties(... LANGUAGE HIP)
PyTorch CUDAExtension + hipify 3rdparty/amd/wheel/sgl-kernel/rocm_hipify.py build_rocm.sh 在执行 CMake 构建前调用它 混合列出 .hip 与 .cu;.cu 在 ROCm 下由 PyTorch 内部 hipify 自动转换

2.2 CMakeLists_rocm.txt 的 SOURCES 示例

cmake 复制代码
set(SOURCES
    ${PROJ_ROOT}/csrc/allreduce/custom_all_reduce.hip
    ${PROJ_ROOT}/csrc/allreduce/deterministic_all_reduce.hip
    ${PROJ_ROOT}/csrc/allreduce/quick_all_reduce.hip      # 注意:仓库里只有 .cu,构建时 hipify 生成同名 .hip
    ${PROJ_ROOT}/csrc/common_extension_rocm.cc
    ${PROJ_ROOT}/csrc/elementwise/activation.hip           # 同理,由 activation.cu hipify 生成
    ${PROJ_ROOT}/csrc/elementwise/deepseek_v4_topk.hip
    ${PROJ_ROOT}/csrc/elementwise/dsv4_norm_rope.hip
    ${PROJ_ROOT}/csrc/elementwise/pos_enc.hip
    ...
)
set_source_files_properties(${SOURCES} PROPERTIES LANGUAGE HIP)

注意:

  • Git 里只存 quick_all_reduce.cu、activation.cu、deepseek_v4_topk.cu 等。
  • CMake 引用的 .hip 版本是 构建期由 hipify 生成的临时产物 (放在 build 目录或被 rocm_hipify.py 就地/临时生成)。

2.3 rocm_hipify.py 的 sources 列表

python 复制代码
sources = [
    "csrc/allreduce/custom_all_reduce.hip",          # 原生 HIP,不 hipify
    "csrc/allreduce/deterministic_all_reduce.hip",   # 原生 HIP,不 hipify
    "csrc/allreduce/quick_all_reduce.cu",            # 由 hipify 转换
    "csrc/common_extension_rocm.cc",
    "csrc/elementwise/activation.cu",                # 由 hipify 转换
    "csrc/elementwise/deepseek_v4_topk.cu",          # 由 hipify 转换
    "csrc/elementwise/dsv4_norm_rope.cu",            # 由 hipify 转换
    "csrc/elementwise/pos_enc.cu",                   # 由 hipify 转换
    # topk.hip is maintained as native HIP instead of being generated from topk.cu.
    "csrc/grammar/apply_token_bitmask_inplace_cuda.cu",
    "csrc/kvcacheio/transfer.cu",
    "csrc/memory/weak_ref_tensor.cpp",
    "csrc/moe/moe_align_kernel.cu",
    "csrc/moe/moe_topk_softmax_kernels.cu",
    "csrc/moe/moe_topk_sigmoid_kernels.cu",
]
  • .hip 文件:直接参与链接,不经过 hipify。
  • .cu 文件:PyTorch 的 CUDAExtension 在 ROCm 环境下自动调用 torch.utils.hipify,把 CUDA 语法/头文件替换为 HIP 等价物。

3. .hip 文件为什么还存在?

3.1 原生 HIP 文件(必须手写,不能由 hipify 从 .cu 得到)

文件 原因
csrc/allreduce/custom_all_reduce.hip AMD 自定义 all-reduce 使用 RCCL/peer-memory 路径,与 NCCL 版本差异大,最早在 PR #3406 引入独立 HIP 实现
csrc/allreduce/deterministic_all_reduce.hip 确定性 all-reduce 的 ROCm 特化实现
csrc/elementwise/topk.hip PR #37591 注释明确说明:topk.hip is maintained as native HIP instead of being generated from topk.cu,使用 DSA cooperative selection 等 AMD 特有逻辑
ops/gemm/smallm_fp8_*.hip gfx950 专用 small-batch FP8 GEMM,新架构特调
ops/moe/smallm_*.hip gfx950 专用 small MoE / router kernel

3.2 构建期生成的 .hip 文件

  • 对应仓库里的 .cu 文件(如 activation.cu、moe_align_kernel.cu)。

  • 这些文件内部通常有 #ifndef USE_ROCM / #else 分支,允许同一份 .cu 同时适配 CUDA 和 ROCm。

  • 例如 activation.cu:

    cpp 复制代码
    #ifndef USE_ROCM
    #include <flashinfer/activation.cuh>
    #else
    #include "hip/hip_act_and_mul.cuh"
    #endif
  • hipify 处理后会得到 .hip 临时文件,再被 CMakeLists_rocm.txt 里的 LANGUAGE HIP 编译。


4. 历史演进:从 .hip 到".cu + 原生 .hip"混合

4.1 早期(sgl-kernel 独立仓库阶段)

  • 存在 sgl-kernel/csrc/allreduce/custom_all_reduce.hip。
  • AMD 支持刚起步时,部分算子直接写 .hip。

4.2 中期(sgl-kernel 并入 python/sglang/kernels/aot)

  • PR #32648 [Kernel] Move sgl-kernel under sglang.kernels.aot 把 AOT kernel wheel 源码从顶层 sgl-kernel/ 移动到 python/sglang/kernels/aot/。
  • 同时保留了 custom_all_reduce.hip / deterministic_all_reduce.hip。

4.3 近期(混合策略)

  • 新增算子(如 deepseek_v4_topk.cu、dsv4_norm_rope.cu)优先以 .cu 形式编写,并用 #ifdef USE_ROCM 做 ROCm 适配。
  • ROCm 构建通过 hipify 自动生成 .hip。
  • 当 hipify 无法满足性能或语义需求时(如 topk cooperative selection、gfx950 smallm kernels),再单独写原生 .hip。

5. 对开发者的实际含义

  1. 不要期望在仓库里看到大量 .hip 文件 。未来新增通用算子大概率仍是 .cu,ROCm 适配走 #ifdef USE_ROCM + hipify。
  2. 需要 AMD 特化性能或新架构(gfx950)支持时 ,才会新增原生 .hip。
  3. 构建 ROCm wheel 时 ,.cu 文件不是直接编译,而是经 hipify 生成 .hip 后再由 hipcc 编译。
  4. CMakeLists_rocm.txt 中引用的 .hip 路径 大部分是构建期产物,Git 中实际跟踪的是同名 .cu;只有少数(custom_all_reduce.hip、deterministic_all_reduce.hip、topk.hip、gfx950 专用 kernel)是真实手写文件。

6. 参考文件

  • CUDA 主构建:python/sglang/kernels/aot/CMakeLists.txt
  • ROCm 构建:3rdparty/amd/wheel/sgl-kernel/CMakeLists_rocm.txt
  • ROCm setuptools/hipify 入口:3rdparty/amd/wheel/sgl-kernel/rocm_hipify.py
  • ROCm wheel 构建脚本:3rdparty/amd/wheel/sgl-kernel/build_rocm.sh
  • AMD 构建说明:3rdparty/amd/wheel/README.md
  • 内核目录说明:python/sglang/kernels/README.md
  • 原生 HIP topk:python/sglang/kernels/aot/csrc/elementwise/topk.hip
  • 双平台 activation:python/sglang/kernels/aot/csrc/elementwise/activation.cu
相关推荐
Eloudy11 小时前
sgl-kernel 项目的演进:不同时间点的角色与去向
llm·sglang
zhangfeng113313 小时前
6篇RAG核心论文的工程启示:Vector + Graph + Agent路由混合架构实战
人工智能·架构·llm·agent
沛东的认知和实践1 天前
当 RAG 开始“要求找全”:一次 Agentic RAG 边界探索与 LLM Wiki 转向
llm·agent
Eloudy1 天前
《Attention Is All You Need》的 Encoder–Decoder Transformer 一次完整训练
llm·transformer
lucas_AI1 天前
自蒸馏也讲究因材施教:让每个 token 自己挑老师,数学推理白捡 5.9 分
llm
ZhengEnCi2 天前
同样的模型,为什么本地和云 API 差别那么大:量化精度、聊天模板与采样参数的三大元凶
人工智能·算法·llm
goehou2 天前
ReAct 循环跑偏的三种样子,以及怎么在工程上兜住
llm·agent·react·工具调用·工程实践
ZhengEnCi2 天前
Agent 如何进行工具调用:从一次 Function Calling 到生产级工具编排的完整链路
llm·agent·ai编程
王博要战斗2 天前
TensorBoard 和 W&B(Wandb) 到底该怎么接进 LLMOps 平台?
llm