Prhub

#23449 [Apple Silicon] Add Metal kernel support in sgl-kernel

原始 PR 作者 yeahdongcn 合并时间 2026-05-12 08:54 文件变更 10 提交数 4 评论 29 代码增减 +594 / -211

执行摘要

为 Apple Silicon 添加 Metal kernel 构建支持

此 PR 源自 #22868 引入的自定义 Metal kernel,社区讨论后决定遵循 SGLang 惯例:自定义 kernel 应放入 sgl-kernel 并以 AOT 方式编译。这样便于统一管理多后端 kernel,并允许 sgl-kernel 在 macOS 上独立安装。

值得精读。该 PR 展示了多后端 kernel 仓库的搭建方式,setup_metal.py 的异常处理和 ccache 集成是良好实践。Review 中关于 AOT/JIT 和 IR 接口的讨论具有技术参考价值。

讨论亮点

review 中讨论了几个关键点:

  • AOT vs JIT:adityavaid 询问编译方式,作者确认已完全改为 AOT。
  • 性能基准:adityavaid 要求 kernel profiling 和 benchmark,作者承认 placeholder 是初始步骤,后续补充。
  • 构建缓存:alexnails 提议引入构建缓存,作者添加了 ccache 支持 C++ 编译,Metal shader 缓存留待后续。
  • 平台检查范围:alexnails 指出 setup_metal.py 对 Intel Mac 也会失败,作者增加 arm64 平台限制。
  • IR 式接口:alexnails 提议采用更抽象的接口统一后端导出,作者同意在后续会议讨论。

实现拆解

  1. 构建脚本:创建 sgl-kernel/setup_metal.py,在模块级别检查 Apple Silicon 和 Xcode 工具链(_ensure_toolchain),自动安装缺失的构建依赖,定义 BuildMetalExtension 类编译 .metal 为 .metallib 并编译 C++ 宿主代码。
  2. Python 入口:新增 sgl-kernel/python/sgl_kernel/metal.py,加载 _metal 扩展并注册 .metallib。修改 init.py,通过平台判断决定导入 Metal 或 CUDA/ROCm ops。
  3. 应用层配合:修改 python/sglang/init.py,将条件从 darwin 扩展为 darwin and arm64,确保 stubs 只安装在 Apple Silicon 上。
  4. 文档更新:补充 apple_metal.mdx 的 Xcode 前提和编译步骤;同步更新 diffusion 安装文档。
  5. 依赖管理:在 pyproject_other.toml 中将 mlx 设置为 >=0.31.1 确保兼容。
文件 模块 状态 重要度
sgl-kernel/setup_metal.py 构建脚本 added 9.08
sgl-kernel/python/sgl_kernel/__init__.py 内核初始化 modified 7.91
sgl-kernel/python/sgl_kernel/metal.py Metal Loader added 6.68
python/sglang/__init__.py 应用入口 modified 4.83
docs_new/docs/hardware-platforms/apple_metal.mdx 文档 modified 3.28

关键符号

_ensure_toolchain _ensure_build_requires _get_version BuildMetalExtension build_extension _python_eval

关键源码片段

sgl-kernel/setup_metal.py dependency-wiring

核心构建脚本,定义 Metal 扩展编译流程和工具链验证

# 检查系统环境:必须为 Apple Silicon macOS 且 Xcode 工具链完整
def _ensure_toolchain():
    if sys.platform != "darwin" or platform.machine() != "arm64":
        raise SystemExit("setup_metal.py only supports macOS (Apple Silicon).")
    if shutil.which("c++") is None or shutil.which("xcrun") is None:
        raise SystemExit("Xcode Command Line Tools 未安装,请运行 xcode-select --install")
    try:
        subprocess.check_output(["xcrun", "-sdk", "macosx", "metal", "--version"])
    except (subprocess.CalledProcessError, FileNotFoundError) as exc:
        raise SystemExit("Metal compiler 未找到,需要安装完整 Xcode") from excclass BuildMetalExtension(build_ext):
    def build_extension(self, ext):
        # 使用 ccache 加速 C++ 编译(如果可用)
        ccache = shutil.which("ccache")
        cxx_cmd = [ccache, "c++"] if ccache else ["c++"]
        # 编译 Metal shader:通过 xcrun metal 生成 .air,再打包为 .metallib
        # 编译 C++ 宿主代码:链接 Metal/Foundation/QuartzCore/MLX 框架
        # 最终通过 nanobind 将 C++ 入口暴露给 Python
        ...
sgl-kernel/python/sgl_kernel/__init__.py core-logic

顶层入口,根据平台条件导入 Metal 或 CUDA ops,是关键分发点

# 在 macOS Apple Silicon 上仅暴露 Metal 扩展,跳过 CUDA 导入
if sys.platform == "darwin" and platform.machine() == "arm64":
    from sgl_kernel.metal import * # 仅导入 metal 模块中定义的符号
else:
    import torch
    from sgl_kernel.debug_utils import maybe_wrap_debug_kernel
    from sgl_kernel.load_utils import _load_architecture_specific_ops, _preload_cuda_library
    # ... 其他所有 GPU 后端的 ops 导入

评论区精华

AOT vs JIT 编译方式 设计

adityavaid 询问 Kernel 编译方式,作者回应已完全改为 AOT,即先将 .metal 编译为 .metallib 再通过 nanobind 嵌入。

结论:确定为 AOT 方式 · 已解决

性能基准要求 性能

adityavaid 要求提供 profiling 和 benchmark 数据,证明 Metal kernel 的实际加速效果。

结论:作者计划后续补充实际 kernel 和 benchmark · unresolved

构建缓存支持 infra

alexnails 询问是否引入构建缓存,作者添加了 ccache 支持 C++ 编译,Metal shader 缓存留待后续。

结论:已支持 ccache,Metal shader 缓存待处理 · partially resolved

平台检查范围 正确性

alexnails 指出 setup_metal.py 对 Intel Mac 也会触发退出,作者最终限制为仅在 Apple Silicon 上运行。

结论:已修复,添加 arm64 检查 · 已解决

IR 式接口设计 设计

alexnails 提议采用更抽象的接口统一各后端,作者同意在后续会议中讨论。

结论:待后续讨论 · unresolved

风险与影响

当前仅占位 kernel,无实际计算逻辑,性能风险低。风险包括:构建脚本高度依赖 Xcode 和 MLX 版本,macOS 更新可能导致兼容性问题;无测试覆盖条件导入逻辑;对 CUDA 后端无影响。

Apple Silicon 用户可通过 sgl-kernel 安装 Metal 原生 kernel(基础设施就绪)。现有 CUDA/ROCm/MUSA 用户无影响。团队需维护 macOS 特定构建分支。

平台特定构建脚本 无测试覆盖 占位 kernel 无实际计算

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论