Prhub

#28770 [MLX] Fix Apple Silicon server startup; align MLX tests with upstream

原始 PR 作者 Toufupi 合并时间 2026-06-24 13:58 文件变更 3 提交数 1 评论 8 代码增减 +120 / -4

执行摘要

修复 MLX 后端启动崩溃并新增内存池覆盖

PR #28660 修复了 initialize 参数问题,但服务器仍因 _init_pools 断言失败而崩溃。根本原因是存根在 initialize() 中自行构建 KV 缓存池,而基类 alloc_memory_pool 调用 _init_pools 并断言 is_draft_worker。通过添加无操作覆盖解决。

值得精读的修补 PR,展示了细粒度覆盖和契约测试的实践。建议关注 alloc_memory_pool 设计模式及签名验证方法。

讨论亮点

yeahdongcn 指出与 #28660 部分重复,但 Toufupi 确认 alloc_memory_pool 路径仍需修复。jlee5814 建议仅保留 alloc_memory_pool 覆盖并添加测试。最终按此方向合并。

实现拆解

  1. 源码修改:在 python/sglang/srt/hardware_backend/mlx/model_runner_stub.pyMlxModelRunnerStub 类中新增 alloc_memory_pool(self, memory_pool_config=None) 方法,直接返回(无操作),避免基类 GPU 分配。
  2. 新增测试:在 test/registered/unit/hardware_backend/mlx/test_mlx_runner_pool_contract.py 中添加三个契约测试,验证覆盖存在性、无参数绑定和可选配置参数绑定。
  3. 测试对齐:修改 test/registered/unit/hardware_backend/mlx/test_attention_patching.py,为 test_finished_request_snapshots_before_release 等测试补充上游新增的属性和存根以通过验证。
文件 模块 状态 重要度
python/sglang/srt/hardware_backend/mlx/model_runner_stub.py MLX 后端 modified 6.05
test/registered/unit/hardware_backend/mlx/test_mlx_runner_pool_contract.py MLX 契约测试 added 7.6
test/registered/unit/hardware_backend/mlx/test_attention_patching.py 注意测试调整 modified 5.89

关键符号

alloc_memory_pool test_stub_overrides_base_alloc_memory_pool test_stub_alloc_memory_pool_binds_with_no_args test_stub_alloc_memory_pool_binds_with_optional_config

关键源码片段

python/sglang/srt/hardware_backend/mlx/model_runner_stub.py data-contract

核心变更,新增 alloc_memory_pool 无操作覆盖。

# python/sglang/srt/hardware_backend/mlx/model_runner_stub.py
# 在 MlxModelRunnerStub 类中新增def alloc_memory_pool(self, memory_pool_config=None):
    """No-op: MLX manages its own KV cache via MlxAttentionKVPool.    The base ``ModelRunner.alloc_memory_pool`` runs ``_init_pools`` which asserts
    ``is_draft_worker`` (model_runner_kv_cache_mixin.py:409). Since the stub
    builds its pools eagerly in ``initialize()``, this method must short-circuit
    the GPU allocation path.
    """
    pass
test/registered/unit/hardware_backend/mlx/test_mlx_runner_pool_contract.py test-coverage

新增契约测试,防止 alloc_memory_pool 覆盖丢失。

# test/registered/unit/hardware_backend/mlx/test_mlx_runner_pool_contract.py
# 新增契约测试类import importlib.util
import inspect
import unittest_HAS_MLX = importlib.util.find_spec("mlx") is not Noneif _HAS_MLX:
    from sglang.srt.hardware_backend.mlx.model_runner_stub import MlxModelRunnerStub
    from sglang.srt.model_executor.model_runner import ModelRunner@unittest.skipUnless(_HAS_MLX, "requires mlx")
class TestMlxRunnerPoolContract(unittest.TestCase):
    """``MlxModelRunnerStub.alloc_memory_pool`` must override the base."""
​
    def test_stub_overrides_base_alloc_memory_pool(self):
        self.assertIn("alloc_memory_pool", vars(MlxModelRunnerStub),
            msg="MlxModelRunnerStub lost its alloc_memory_pool override.")
        self.assertIsNot(MlxModelRunnerStub.alloc_memory_pool,
                         ModelRunner.alloc_memory_pool,
                         msg="Must be overridden, not inherited.")
​
    def test_stub_alloc_memory_pool_binds_with_no_args(self):
        sig = inspect.signature(MlxModelRunnerStub.alloc_memory_pool)
        try:
            sig.bind(object())
        except TypeError as exc:
            self.fail(f"Must accept no-arg call: {exc}")
​
    def test_stub_alloc_memory_pool_binds_with_optional_config(self):
        # _FakeConfig is a simple stub for MemoryPoolConfig
        class _FakeConfig:
            pass
        sig = inspect.signature(MlxModelRunnerStub.alloc_memory_pool)
        try:
            sig.bind(object(), _FakeConfig())
        except TypeError as exc:
            self.fail(f"Must accept optional config argument: {exc}")

评论区精华

initialize 参数修复重复与 alloc_memory_pool 必要性 设计

yeahdongcn 指出 #28770 与 #28660 部分重复,但 @Toufupi 指出 #28660 后服务器仍无法启动,因为 _init_pools 断言。@jlee5814 确认 initialize 参数修复重复,但 alloc_memory_pool 路径仍需修复。

结论:保留 alloc_memory_pool 覆盖并添加契约测试,舍弃重复的 initialize 参数更改。 · 已解决

要求添加单元测试 测试

yeahdongcn 要求 @Toufupi rebase 并添加必要的单元测试,类似 #28660。

结论:Toufupi 完成 rebase,保留 alloc_memory_pool 覆盖,添加单元测试并修复 test_attention_patching.py。 · 已解决

风险与影响

仅影响 MLX 后端,风险较低。主要风险是未来上游重构 alloc_memory_pool 签名时覆盖可能失效,但已通过契约测试降低该风险。

对用户:MLX 后端可正常启动;对系统:仅 MLX 路径受影响;对团队:明确了 MLX 内存池管理策略。

MLX 后端变更 回归风险低 契约测试防护

关联 Issue

未识别关联 Issue

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

完整报告

参与讨论