# PR #35711 完整报告

- 仓库：`sgl-project/sglang`
- 标题：[Runtime] Don't override CUDA_MODULE_LOADING
- 合并时间：2026-08-22 05:09
- 原文链接：http://prhub.com.cn/sgl-project/sglang/pull/35711

---

# 执行摘要

- 一句话：不再强制覆盖 CUDA_MODULE_LOADING 环境变量
- 推荐动作：不值得逐行精读代码（仅 1 行删除），但 PR body 是 " 删除环境变量强制覆盖前，先用官方契约 + 真实环境实测交叉验证 " 的优质范本，建议快速阅读其动机与验证段落。值得关注的设计决策是：SGLang 不再替用户决定 CUDA 模块加载策略，而是交给部署方和 CUDA / PyTorch 栈；若团队后续需要统一 lazy 策略，应通过部署模板或文档显式设置，而不是在代码里写死未文档化的 `AUTO`。

# 功能与动机

PR body 明确指出：`_set_envs_and_config()` 在启动 scheduler worker 前赋值 `CUDA_MODULE_LOADING=AUTO`，会静默替换部署方显式的 `DEFAULT` / `EAGER` / `LAZY` 选择，而 `AUTO` 不在 NVIDIA CUDA Programming Guide 的合法取值清单内，其行为也不属于 NVIDIA 的兼容性契约。典型受影响场景是部署方有意使用 `EAGER`，把首次使用时的模块初始化移出请求路径，以换取更可预测的请求延迟；该设置此前会在本地 multiprocessing worker 派生前被覆盖。作者还引用 NVIDIA Lazy Loading guide 的版本边界说明：CUDA 12.2（Linux）起 lazy loading 成为默认，因此未设置变量时应跟随已安装 CUDA / PyTorch 栈，而不是由 SGLang 强制写入一个未文档化的值。

# 实现拆解

1. 定位强制覆盖点：`_set_envs_and_config()` 位于 `python/sglang/srt/entrypoints/engine.py`，负责本地 worker 启动前的全局环境准备；其中在设置 `CUDA_DEVICE_MAX_CONNECTIONS` 之后，有一行无条件写入 `os.environ["CUDA_MODULE_LOADING"] = "AUTO"`。
2. 删除该无条件赋值：移除后，用户已在环境中设置好的 `DEFAULT` / `EAGER` / `LAZY` 会在 multiprocessing worker 派生前完整保留；变量完全缺失时，行为交给底层 CUDA / PyTorch 栈的默认策略，而不是沿用 SGLang 写死的未文档化值。
3. 边界与配套：本 PR 未新增 CLI 参数、未改动 `CUDA_DEVICE_MAX_CONNECTIONS`、未更新文档与测试；Ray 场景需要在集群或作业运行时环境中显式携带该变量才能可靠传播。作者在 CUDA 13 环境用 `cuModuleGetLoadingMode()` 实测：unset、`DEFAULT`、`LAZY`、`AUTO` 均表现为 `LAZY`，`EAGER` 表现为 `EAGER`；其中 `AUTO` 的结果仅作为该环境的观测，不视为跨版本保证。

关键文件：
- `python/sglang/srt/entrypoints/engine.py`（模块 启动入口；类别 source；类型 core-logic；符号 _set_envs_and_config）: 唯一改动文件：在 `_set_envs_and_config()` 环境准备逻辑中删除了对 `CUDA_MODULE_LOADING=AUTO` 的无条件赋值，是本次行为的全部来源。

关键符号：_set_envs_and_config

## 关键源码片段

### `python/sglang/srt/entrypoints/engine.py`

唯一改动文件：在 `_set_envs_and_config()` 环境准备逻辑中删除了对 `CUDA_MODULE_LOADING=AUTO` 的无条件赋值，是本次行为的全部来源。

```python
def _set_envs_and_config(server_args: ServerArgs):
    # 设置全局环境变量；本 PR 之前，这里在 CUDA_DEVICE_MAX_CONNECTIONS 之后
    # 无条件写入 os.environ["CUDA_MODULE_LOADING"] = "AUTO"，会覆盖部署方
    # 显式设置的 DEFAULT / EAGER / LAZY。AUTO 并非 NVIDIA 文档化值。
    # 删除后：用户已设置则保留原值；未设置则跟随 CUDA / PyTorch 栈默认
    # （CUDA 12.3+ 默认 lazy loading）。
    if server_args.nnodes > 1 and is_mnnvl_fabric_device():
        os.environ.setdefault("NCCL_CUMEM_ENABLE", "1")
        os.environ.setdefault("NCCL_MNNVL_ENABLE", "1")
    if "NCCL_CUMEM_ENABLE" not in os.environ or server_args.enable_symm_mem:
        os.environ["NCCL_CUMEM_ENABLE"] = str(int(server_args.enable_symm_mem))
    if (
        "NCCL_NVLS_ENABLE" not in os.environ
        or server_args.enable_nccl_nvls
        or server_args.enable_symm_mem
    ):
        os.environ["NCCL_NVLS_ENABLE"] = str(
            int(server_args.enable_nccl_nvls or server_args.enable_symm_mem)
        )
    if "NCCL_GRAPH_MIXING_SUPPORT" not in os.environ or server_args.enable_symm_mem:
        # Note(wh): NCCL_GRAPH_MIXING_SUPPORT=0 对对称内核有性能收益
        # 详见 https://github.com/NVIDIA/nccl-tests/issues/333#issuecomment-3103636985
        if server_args.dcp_size > 1:
            os.environ["NCCL_GRAPH_MIXING_SUPPORT"] = "0"
    os.environ["CUDA_DEVICE_MAX_CONNECTIONS"] = "8"
    # 此处删除了 os.environ["CUDA_MODULE_LOADING"] = "AUTO"，
    # 使 CUDA_MODULE_LOADING 不再被隐式改写（详见 PR #35711 动机）。

```

# 评论区精华

该 PR 的审阅过程没有出现技术争论：ShangmingCai 以 "LGTM" 批准，ispobock 以空附言批准。唯一的 issue 评论是 ShangmingCai 的 `/tag-and-rerun-ci`，仅用于触发 CI 重跑。需要注意的是，三个 CI run（PR Test、Extra、AMD ROCm 7.2）在记录中均显示为 ✗，但 PR 内没有对应讨论，无法确认失败原因是否与本次改动相关。

- 暂无高价值评论线程

# 风险与影响

- 风险：
 - 行为依赖 CUDA 版本：删除强制赋值后，未设置 `CUDA_MODULE_LOADING` 的环境将跟随 CUDA / PyTorch 栈默认。CUDA 12.3+（Linux）默认 lazy loading，与现代默认一致；但老环境（如 CUDA 11.x 默认 eager 或自定义配置）下行为会与之前不同，首次 kernel 加载可能出现在请求路径中，影响首个请求延迟。
 - `AUTO` 语义不可依赖：作者在 CUDA 13 上观测到 `AUTO` 表现为 `LAZY`，但这是单环境观测而非 NVIDIA 契约，跨版本可能漂移；任何此前依赖该行隐含行为的部署都需自行确认。
 - 缺少测试覆盖：本 PR 无对应单元测试或集成测试，验证完全依赖人工实测（CUDA 13 环境）。
 - CI 状态：三个 CI run 均失败且无讨论说明，需确认是既有基线问题还是本次改动引入。
- 影响：
 - 用户侧：显式设置 `CUDA_MODULE_LOADING` 的部署（特别是用 `EAGER` 换取可预测请求延迟的场景）恢复预期行为；未设置的部署在现代 CUDA 下行为基本不变，仍是 lazy loading。
 - 系统侧：影响本地 multiprocessing worker 派生前的 CUDA 上下文准备；Ray 等远程 actor 场景需要由集群层显式传递该变量。
 - 团队侧：单行删除、回归面极小，但 PR body 对 NVIDIA 官方契约的引用与真实环境实测交叉验证的方式，可作为后续环境变量治理的参考先例。
 - 风险标记：环境变量行为依赖 CUDA 版本 , 缺少测试覆盖 , CI 失败未解释

# 关联脉络

- PR #35910 config: publish before the launcher reads effective configuration: 同样改动 python/sglang/srt/entrypoints/engine.py 的启动期配置处理，与本 PR 同属 runtime 启动链路的环境 / 配置治理演进，但关注点不同（配置发布时机 vs 环境变量覆盖）。
- PR #35907 config: constructing a config no longer resolves it: 同批 config 重构系列之一，收敛 ServerArgs 解析与启动期隐式副作用，与本 PR 都在削减运行时启动阶段的隐式行为。