Prhub

#22123 Add Arm64 CPU Phase 1A CI bootstrap

原始 PR 作者 ranimandepudi 合并时间 2026-05-08 09:28 文件变更 7 提交数 6 评论 12 代码增减 +272 / -22

执行摘要

为 Arm64 CPU 添加 CI 构建与测试引导支持

Arm64 此前缺乏首等的 CPU PR 构建与功能子集验证流水线。CPU backend 的默认选项仍以 Intel 为先,在 Arm64 上并非正确的默认值。部分 CPU kernel 仍然依赖 x86 特有的 AMX/AVX512 假设,因此引导支持需要临时、明确的作用域修剪,而不是假装这些路径已经可移植。

该 PR 是 Arm64 支持的第一步,其采用的渐进式集成策略(通过条件编译隔离不可移植部分,而不是一次性全量支持)值得借鉴。建议重点关注 server_args.py 中的后端选择策略和 sgl-kernel 中的条件编译模式,后续扩展时可复用此框架。团队应建立约定:所有 x86-only 的 kernel 添加时,必须同步更新 CMakeLists.txt 中的排除列表和宏保护。

讨论亮点
  • Dockerfile 最佳实践:gemini-code-assist[bot] 建议避免 apt-get full-upgrade 以保证确定性构建,并使用 ENV 设置 PATH 而非修改 .bashrc
  • 测试有效性:cyb70289 认为测试不够有用,且仅加入 Arm 套件会导致 x86 路径未被 Xeon CI 覆盖。ranimandepudi 回复将精简测试并同时加入 Xeon 套件(最终采纳)。
  • 宏命名简化:mingfeima 建议使用更简单的宏名称,ranimandepudi 采纳并简化为 SGLANG_CPU_ARM64_SKIP_X86_ONLY_OPS
  • 整体认可:cyb70289 最终给出 LGTM 并批准。

实现拆解

  1. CI 工作流与 Docker 镜像:新增 .github/workflows/pr-test-arm64.yml 定义 Arm64 专用 CI 流水线,使用 ubuntu-24.04-arm 运行器;新增 docker/arm64.Dockerfile 基于 Ubuntu 24.04 构建含 Python 3.12 和 PyTorch CPU 版的镜像,并编译安装 sglang 和 sgl-kernel。

  2. CPU backend 默认选择:修改 python/sglang/srt/server_args.py 中的 _handle_cpu_backends 方法,引入 is_host_cpu_arm64() 判断,若为 Arm64 则默认 attention_backend = "torch_native",否则保持 "intel_amx";同时导入 is_host_cpu_arm64 工具函数。

  3. Kernel 构建条件编译:在 sgl-kernel/csrc/cpu/CMakeLists.txt 中定义 x86-only 源文件列表(如 gemm_int4.cppmoe.cpp 等),通过 SGLANG_CPU_ARM64_SKIP_X86_ONLY_OPS 宏在 Arm64 构建时移除这些文件并添加编译定义;在 sgl-kernel/csrc/cpu/torch_extension_cpu.cpp 中使用 #if !defined(SGLANG_CPU_ARM64_SKIP_X86_ONLY_OPS) 包裹相应函数声明和 TORCH_LIBRARY 注册,防止 Arm64 链接失败。

  4. 测试套件:新增 test/srt/cpu/test_server_args_backend.py 使用 mock 验证不同架构下的默认 backend 选择;在 test/srt/run_suite.py 中添加 suite_arm64(含 7 个测试)和 "per-commit-cpu-arm64" 测试集合,同时将 backend 选择测试加入 Xeon CPU 套件以确保 x86 路径也得到执行。

文件 模块 状态 重要度
test/srt/cpu/test_server_args_backend.py 后端选择 added 7.09
python/sglang/srt/server_args.py 服务配置 modified 6.28
sgl-kernel/csrc/cpu/torch_extension_cpu.cpp CPU 内核 modified 6.73
.github/workflows/pr-test-arm64.yml CI 配置 added 5.84
docker/arm64.Dockerfile Docker added 4.99
test/srt/run_suite.py 测试编排 modified 4.84
sgl-kernel/csrc/cpu/CMakeLists.txt 构建系统 modified 3.32

关键符号

_handle_cpu_backends is_host_cpu_arm64 TestServerArgsCPUBackend._make_server_args TestServerArgsCPUBackend.test_arm_cpu_defaults_to_torch_native TestServerArgsCPUBackend.test_x86_cpu_defaults_to_intel_amx

关键源码片段

python/sglang/srt/server_args.py core-logic

核心逻辑修改,根据 CPU 架构动态选择 attention backend,是 Arm64 默认行为的关键变化。

# 在文件头部的 import 块中新增一行:
from sglang.srt.utils.common import (
    # ... 其他导入
    is_host_cpu_arm64, # 新增导入,用于检测 Arm64 架构
    # ...
)# _handle_cpu_backends 方法的变更(约第 1148 行):
def _handle_cpu_backends(self):
    if self.device == "cpu":
        if self.attention_backend is None:
            # Arm64 默认使用 torch_native(纯 PyTorch 实现),
            # x86 保持 intel_amx(利用 AMX 指令加速)
            self.attention_backend = (
                "torch_native" if is_host_cpu_arm64() else "intel_amx"
            )
        self.sampling_backend = "pytorch"
sgl-kernel/csrc/cpu/torch_extension_cpu.cpp core-logic

使用条件编译宏屏蔽 x86-only 内核声明和注册,避免 Arm64 构建链接失败。

// 以下函数声明仅在非 Arm64 构建时可用
#if !defined(SGLANG_CPU_ARM64_SKIP_X86_ONLY_OPS)
// int4 gemm
at::Tensor int4_scaled_mm_cpu(
    at::Tensor& x, at::Tensor& w, at::Tensor& w_zeros, at::Tensor& w_scales, std::optional<at::Tensor> bias);// weight prepack for int4 weights
std::tuple<at::Tensor, at::Tensor, at::Tensor> convert_weight_packed_scale_zp(
    at::Tensor qweight,
    at::Tensor qzeros,
    at::Tensor scales,
    int64_t quant_method_4bit);
#endif// gemm(通用,不依赖 x86 特定指令)
at::Tensor weight_packed_linear(at::Tensor& mat1, at::Tensor& mat2, const std::optional<at::Tensor>& bias, bool is_vnni);// ... 其他通用声明// 对应的 TORCH_LIBRARY 注册也使用相同条件
#if !defined(SGLANG_CPU_ARM64_SKIP_X86_ONLY_OPS)
m.def("int4_scaled_mm_cpu(...)", ...);
m.impl("int4_scaled_mm_cpu", torch::kCPU, &int4_scaled_mm_cpu);
#endif

评论区精华

Dockerfile 使用 apt-get full-upgrade 和 PATH 设置 other

gemini-code-assist[bot] 指出 apt-get full-upgrade 会导致非确定性构建,建议仅安装所需包;并建议使用 ENV 设置 PATH 替代修改 .bashrc。

结论:PR 未修改 Dockerfile,但评论者提出了好的实践建议,作者可能后续跟进。 · 待处理

测试有效性及套件覆盖范围 测试

cyb70289 认为 test_server_args_backend.py 测试不够有用,且只加入 Arm 套件会导致 x86 路径未被 Xeon CI 覆盖。ranimandepudi 回复将精简测试(移除显式 backend 测试)并同时加入 Xeon 套件。

结论:最终实现:测试保留了默认值选择测试,并加入了 Xeon 套件(suites['per-commit-cpu'] 中增加了该测试)。 · 已解决

宏命名简化 设计

mingfeima 建议使用更简单的宏名称。ranimandepudi 采纳并简化为 SGLANG_CPU_ARM64_SKIP_X86_ONLY_OPS。

结论:宏名称从提议的 SGLANG_CPU_ARM64_BOOTSTRAP_SKIP_X86_ONLY 简化为 SGLANG_CPU_ARM64_SKIP_X86_ONLY_OPS。 · 已解决

风险与影响

  • 兼容性风险:条件编译宏 SGLANG_CPU_ARM64_SKIP_X86_ONLY_OPS 用于屏蔽 x86-only 源码和注册,但若后续新增 x86-only 函数时忘记同步添加宏保护,会导致 Arm64 构建出现未定义符号。
  • 回归风险server_args.py 中的后端选择逻辑对 x86 行为无变化(依然默认 intel_amx),但 is_host_cpu_arm64() 函数依赖于 platform.machine(),若在模拟环境(如 QEMU user-mode)中误判,可能导致 x86 机器意外选择了 torch_native
  • 测试覆盖有限:Phase 1A 测试套件仅包含 7 个测试文件,无法覆盖 Arm64 CPU 的完整推理功能,特别是 test_extend.pytest_mamba.pytest_mla.py 等已知阻塞项仍被排除。
  • 维护负担:构建系统中新增了条件分支和源文件列表,增加了维护复杂性,后续开发需要留意保持与 x86 的同步。
  • 用户影响:Arm64 CPU 用户可使用 sglang 进行受限的 CPU 推理(后端选择为 torch_native),但 MoE、int4 量化、QKV projection with RoPE 等功能在 Arm64 上暂时不可用,直到后续阶段落地原生内核或 fallback。
  • 系统影响:CI 中新增了 Arm64 专用流水线,增加了 GitHub Actions 运行时长和资源消耗;构建系统增加了条件编译分支,提高了维护复杂性。
  • 团队影响:ARM 团队可在此基础设施上迭代添加 Arm64 原生内核和测试,Intel 团队需要确保未来合入的 x86-only 代码正确添加宏保护。
x86-specific kernel 跳过可能导致功能缺失 条件编译宏可能不同步 测试覆盖有限 CI 资源增加

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论