# PR #22123 完整报告

- 仓库：`sgl-project/sglang`
- 标题：Add Arm64 CPU Phase 1A CI bootstrap
- 合并时间：2026-05-08 09:28
- 原文链接：http://prhub.com.cn/sgl-project/sglang/pull/22123

---

# 执行摘要

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

# 功能与动机

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

# 实现拆解

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.cpp`、`moe.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`（模块 后端选择；类别 test；类型 test-coverage；符号 TestServerArgsCPUBackend, _make_server_args, test_arm_cpu_defaults_to_torch_native, test_x86_cpu_defaults_to_intel_amx）: 新增文件，验证不同 CPU 架构下的默认 backend 选择（torch_native vs intel_amx），是核心逻辑的回归测试。
- `python/sglang/srt/server_args.py`（模块 服务配置；类别 source；类型 core-logic；符号 _handle_cpu_backends, is_host_cpu_arm64）: 核心逻辑修改，根据 CPU 架构动态选择 attention backend，是 Arm64 默认行为的关键变化。
- `sgl-kernel/csrc/cpu/torch_extension_cpu.cpp`（模块 CPU 内核；类别 source；类型 core-logic）: 使用条件编译宏屏蔽 x86-only 内核声明和注册，避免 Arm64 构建链接失败。
- `.github/workflows/pr-test-arm64.yml`（模块 CI 配置；类别 infra；类型 infrastructure）: 新增的 Arm64 CI 工作流，定义了整个构建和测试流水线。
- `docker/arm64.Dockerfile`（模块 Docker；类别 infra；类型 infrastructure）: Arm64 专用 Docker 镜像，用于 CI 集成。
- `test/srt/run_suite.py`（模块 测试编排；类别 test；类型 test-coverage）: 添加 Arm64 引导测试套件，并将 backend 选择测试加入 Xeon 套件。
- `sgl-kernel/csrc/cpu/CMakeLists.txt`（模块 构建系统；类别 infra；类型 infrastructure）: 构建系统调整，定义 x86-only 源文件列表，在 Arm64 构建时移除。

关键符号：_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`

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

```python
# 在文件头部的 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`

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

```cpp
// 以下函数声明仅在非 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 最佳实践**：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 并批准。

 - Dockerfile 使用 apt-get full-upgrade 和 PATH 设置 (other): PR 未修改 Dockerfile，但评论者提出了好的实践建议，作者可能后续跟进。
 - 测试有效性及套件覆盖范围 (testing): 最终实现：测试保留了默认值选择测试，并加入了 Xeon 套件（suites['per-commit-cpu'] 中增加了该测试）。
- 宏命名简化 (design): 宏名称从提议的 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.py`、`test_mamba.py`、`test_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 资源增加

# 关联脉络

- 暂无明显关联 PR