# PR #28113 完整报告

- 仓库：`sgl-project/sglang`
- 标题：[Platform] Route pin memory availability through current_platform
- 合并时间：2026-07-14 02:37
- 原文链接：http://prhub.com.cn/sgl-project/sglang/pull/28113

---

# 执行摘要

- 一句话：将固定内存可用性检查路由至平台抽象层
- 推荐动作：此 PR 值得精读，特别是涉及平台抽象接口设计的地方。设计决策（将钩子放在 DeviceMixin 而非 SRTPlatform）体现了单一职责和开闭原则，对后续 OOT 平台开发有参考价值。用例覆盖全面，测试边界清晰，可视为平台抽象层演进的良好范例。

# 功能与动机

OOT 平台可以实现 `SRTPlatform.is_pin_memory_available()`，但公共辅助函数 `is_pin_memory_available()` 在 `torch.cuda.is_available()` 为 false 时直接返回 False，不咨询平台。这阻止了 Non-CUDA OOT 硬件插件通过平台接口显式启用固定内存支持。

# 实现拆解

1. **在 `DeviceMixin` 基类中新增 `is_pin_memory_available` 方法 **（`python/sglang/srt/platforms/device_mixin.py`）：定义接受可选 `device` 参数的接口，默认返回保守值 `False`，确保 OOT 平台未覆盖时行为安全。
2. **在 `CudaDeviceMixin` 中覆盖该方法 **（`python/sglang/srt/platforms/cuda.py`）：返回 `True` 除非指定 `device='cpu'`，保留 CUDA 平台的固定内存支持。
3. **更新 `CpuSRTPlatform` 的方法签名 **（`python/sglang/srt/platforms/cpu.py`）：添加 `device` 参数，仍返回 `False`，明确表达 CPU 平台不支持固定内存。
4. **从 `SRTPlatform` 中删除旧的默认实现 **（`python/sglang/srt/platforms/interface.py`）：移除原本返回 `True` 的 `is_pin_memory_available()`，避免继承链中的歧义。
5. **重构 `common.is_pin_memory_available` 包装器 **（`python/sglang/srt/utils/common.py`）：将逻辑简化为直接委托给 `current_platform.is_pin_memory_available(device)`，移除硬编码的 CUDA 检查。
6. **增加单元测试 **（`test/registered/unit/platforms/test_platform_interface.py`）：覆盖 OOT 覆盖返回 `True`/`False`、无覆盖时的 CUDA 行为、CPU 设备处理、以及 SRTPlatform 与 DeviceMixin 的协作场景。
7. **更新插件文档 **（`docs_new/docs/hardware-platforms/plugin.mdx`）：说明 pin memory 钩子的使用方法。

关键文件：
- `test/registered/unit/platforms/test_platform_interface.py`（模块 平台接口；类别 test；类型 test-coverage；符号 test_pin_memory_default_is_conservative, test_base_pin_memory_default_is_conservative, test_pin_memory_available_for_cuda_targets, test_rocm_inherits_cuda_pin_memory_behavior）: 新增大量测试用例覆盖 pin memory 可用性的各种场景，是验证正确性的关键。
- `python/sglang/srt/platforms/cuda.py`（模块 CUDA 平台；类别 source；类型 core-logic；符号 is_pin_memory_available）: 在 CudaDeviceMixin 中新增 is_pin_memory_available 覆盖，是 pin memory 支持的核心实现。
- `python/sglang/srt/platforms/device_mixin.py`（模块 设备混入；类别 source；类型 core-logic；符号 is_pin_memory_available）: 在 DeviceMixin 基类中定义默认的 is_pin_memory_available 方法，确立平台抽象契约。
- `python/sglang/srt/platforms/cpu.py`（模块 CPU 平台；类别 source；类型 core-logic；符号 is_pin_memory_available）: 更新 CpuSRTPlatform 的 is_pin_memory_available 方法签名，明确返回 False。
- `python/sglang/srt/platforms/interface.py`（模块 平台接口；类别 source；类型 core-logic；符号 is_pin_memory_available）: 从 SRTPlatform 中移除旧的 is_pin_memory_available 方法，避免与 DeviceMixin 冲突。
- `python/sglang/srt/utils/common.py`（模块 工具函数；类别 source；类型 core-logic）: 简化公共包装器，将固定内存可用性决策完全委托给 current_platform。
- `docs_new/docs/hardware-platforms/plugin.mdx`（模块 文档；类别 other；类型 documentation）: 更新文档说明 pin memory 钩子的使用方式。

关键符号：is_pin_memory_available, test_pin_memory_default_is_conservative, test_base_pin_memory_default_is_conservative, test_pin_memory_available_for_cuda_targets, test_rocm_inherits_cuda_pin_memory_behavior, test_srt_platform_does_not_shadow_device_mixin_pin_memory_override

## 关键源码片段

### `test/registered/unit/platforms/test_platform_interface.py`

新增大量测试用例覆盖 pin memory 可用性的各种场景，是验证正确性的关键。

```python
# 测试 OOT 平台默认保守行为
def test_pin_memory_default_is_conservative(self):
    # 创建一个 OOT DeviceMixin 实例
    mixin = _make_device_mixin(PlatformEnum.OOT, "custom", "custom")
    # 不使用 device 参数和 device="cpu" 都应返回 False
    self.assertFalse(mixin.is_pin_memory_available())
    self.assertFalse(mixin.is_pin_memory_available(device="cpu"))

# 测试 SRTPlatform 基类默认保守行为
def test_base_pin_memory_default_is_conservative(self):
    base = SRTPlatform()
    self.assertFalse(base.is_pin_memory_available())
    self.assertFalse(base.is_pin_memory_available(device="cpu"))

# 测试 CUDA 平台返回 True（除 cpu 外）
def test_pin_memory_available_for_cuda_targets(self):
    base = CudaSRTPlatform()
    self.assertTrue(base.is_pin_memory_available())
    self.assertTrue(base.is_pin_memory_available(device="cuda"))
    self.assertTrue(base.is_pin_memory_available(device=torch.device("cuda", 0)))
    self.assertFalse(base.is_pin_memory_available(device="cpu"))

# 测试 ROCm 继承 CUDA 行为
def test_rocm_inherits_cuda_pin_memory_behavior(self):
    base = RocmSRTPlatform()
    self.assertTrue(base.is_pin_memory_available())
    self.assertTrue(base.is_pin_memory_available(device="cuda"))
    self.assertFalse(base.is_pin_memory_available(device="cpu"))

```

### `python/sglang/srt/platforms/cuda.py`

在 CudaDeviceMixin 中新增 is_pin_memory_available 覆盖，是 pin memory 支持的核心实现。

```python
def is_pin_memory_available(self, device=None) -> bool:
    """CUDA 平台固定内存可用，除非 device 显式指定为 cpu。"""
    # 如果 device 不是 None 且字符串化为 "cpu"，则返回 False
    if device is not None and str(device) == "cpu":
        return False
    # 其余情况（包括默认 None 或 torch.device("cuda", ...)）返回 True
    return True

```

# 评论区精华

Review 中主要讨论了设计归属问题。最初 `is_pin_memory_available` 被提议放在 `SRTPlatform`，但 `AgainstEntropy` 指出在基类中使用 `torch.cuda.is_available()` 不合适，并建议只在 `DeviceMixin` 中放置该方法，允许 OOT 平台通过多态覆盖。最终采纳了此建议，将钩子下移至 `DeviceMixin`，保持 `SRTPlatform` 不直接持有该逻辑。此外，有关于公共包装器 `common.is_pin_memory_available` 的讨论：`AgainstEntropy` 提出应直接委托给 `current_platform`，避免为兼容旧无参覆盖而保留分支，最终也按此简化。

- is_pin_memory_available 应放在 DeviceMixin 还是 SRTPlatform (design): 函数移至 DeviceMixin 作为基础接口，SRTPlatform 不再拥有该方法。
- 公共包装器 common.is_pin_memory_available 的实现简化 (correctness): 公共包装器改为单行委托，不再保留兼容分支。

# 风险与影响

- 风险：此 PR 的主要风险在于平台抽象层的更改可能影响 OOT 平台的行为。但由于默认行为保守（OOT 默认返回 `False`，CUDA 平台仍返回 `True`），且测试覆盖了各种场景，回归风险较低。性能上无影响。安全性无影响。兼容性方面，旧的无参覆盖在调用 `common.is_pin_memory_available()` 时可能因参数数量不匹配而失败，但 `common` 包装器已支持无参调用，且 OOT 平台如果未更新覆盖，则会走默认 `False`，行为安全。
- 影响：对最终用户：无行为变化，CUDA 用户继续享受固定内存支持，CPU 和其他平台行为保持不变。对 OOT 平台开发者：获得了一个可覆盖的钩子，用于显式启用固定内存。对系统：平台抽象更加清晰，职责更单一。对团队：需要了解新的平台接口设计模式。影响范围仅限于平台初始化阶段，不涉及推理路径。
- 风险标记：平台抽象变更 , OOT 扩展兼容性 , 无参覆盖兼容

# 关联脉络

- 暂无明显关联 PR