slime 外部 Rollout 引擎接入指南:跨集群权重同步与训练/推理解耦实践
2026/9/16 23:03:45 网站建设 项目流程

slime 外部 Rollout 引擎接入指南:跨集群权重同步与训练/推理解耦实践

【免费下载链接】slimeslime is an LLM post-training framework for RL Scaling.项目地址: https://gitcode.com/GitHub_Trending/slime12/slime

在 LLM 后训练(RL 训练)中,当推理服务由训练作业之外的系统负责部署与生命周期管理时,slime 需要一种"只接入、不接管"的模式:连接已启动的 SGLang 引擎、注册路由器,并在需要时同步更新后的 Actor 权重。本文以 external-rollout-engines.md 为骨架,结合 slime 源码中的发现机制、权重同步参数与校验逻辑,系统讲解外部 Rollout 引擎的使用场景、配置方式、磁盘全量/增量权重更新方案,以及部署时的注意事项。读完本文,你将能够独立判断何时使用--rollout-external-engine-addrs、何时继续使用--sglang-config,并为跨集群、跨数据中心的训练/推理拆分场景选择正确的权重同步路径。

什么是外部 Rollout 引擎

外部 Rollout 引擎(external rollout engine)是指不是由 slime 训练作业启动的 SGLang 引擎。在这种部署形态下:

  • 另一个系统负责部署引擎并拥有其生命周期;
  • slime 在训练期间只负责连接这些引擎;
  • slime 为这些引擎注册路由器(router);
  • 需要时,slime 将更新后的 Actor 权重同步到引擎侧。

这一路径天然适合推理服务归属于训练作业之外的部署形态,例如:独立的推理集群、独立的 Ray 集群、预先手动预热的 SGLang 引擎,或由其他编排系统托管的 rollout 服务。

何时使用外部引擎:决策表

原文档给出的选择矩阵是判断接入方式的首要依据,先明确你的目标与对应入口:

目标推荐入口
引擎已由外部启动,slime 只需连接做 rollout--rollout-external-engine-addrs
slime 仍需自己启动引擎,但需要 PD 分离、多模型服务、异构服务器组或按组覆盖配置SGLang Config
训练器与外部引擎可以组成 NCCL 组默认--update-weight-mode full --update-weight-transport nccl
训练器与外部引擎无法组成 NCCL 组,但能看到同一文件系统路径--update-weight-mode full --update-weight-transport disk
大模型跨集群或跨数据中心同步时全量 checkpoint 太重--update-weight-mode delta --update-weight-transport disk
rollout 服务使用独立的 SGLang 环境,甚至不同的 GPU 型号/厂商外部引擎 + disk 传输
需要冻结的参考模型、奖励模型或工具侧模型优先在 SGLang Config 中设置update_weights: false

需要特别记住一条硬约束:Delta 模式只支持磁盘传输。需要在 NCCL 上同步权重时,请使用全量模式。

快速上手:连接已启动的外部引擎

首先独立启动 SGLang 服务器(这部分完全由外部系统负责,slime 不参与启动):

python -m sglang.launch_server --model-path /path/to/model --port 10090 ... python -m sglang.launch_server --model-path /path/to/model --port 10091 ...

然后将这些地址传给训练作业:

python train.py \ --rollout-external-engine-addrs host1:10090 host2:10091 \ ...

--rollout-external-engine-addrs参数在 slime/utils/arguments.py 中定义为可接受多个值的参数(nargs="+"),因此可以一次性传入多个host:port

slime 会依次查询每个引擎的/server_info/get_server_info端点,推断出 GPU 数量、TP/PP 信息以及 worker 类型(regularprefilldecode)。如果未提供--sglang-router-ip/--sglang-router-port,slime 会自己启动一个路由器,并将这些外部引擎注册到其中。

地址归一化规则

在 slime/backends/sglang_utils/external.py 中,normalize_external_engine_addr会统一处理地址格式:

  • 支持host:porthttp://host:port两种写法,统一归一化为 HTTP base URL;
  • 若地址缺少协议前缀,自动补上http://
  • 若地址不含端口或 scheme 不是http,会抛出ValueError(IPv6 地址必须加方括号)。

引擎信息发现机制

discover_external_engines(external.py)遍历所有地址,逐个请求/server_info(失败时回退到/get_server_info,见get_server_info),并从返回的 JSON 中解析出:

  • pp_size/pipeline_parallel_size:流水线并行度;
  • tp_size/tensor_parallel_size:张量并行度;
  • num_gpus/num_gpus_per_engine:引擎占用的 GPU 数(缺省时按tp_size * pp_size推算);
  • ep_size/expert_parallel_size:专家并行度;
  • moe_dp_size/moe_data_parallel_size:MoE 数据并行度;
  • disaggregation_mode:用于判断 worker 类型(prefill/decode/null);
  • disaggregation_bootstrap_port:PD 分离场景下 prefill 引擎的引导端口;
  • encoder_only:编码器专用引擎标记。

_infer_worker_type(external.py)根据这些字段决定 worker 类型:encoder_onlyencoderdisaggregation_modeprefill/decode时取对应值,其余为regular。这些信息随后被封装为ExternalEngineInfo(external.py),其is_pd_worker属性可判断是否为 PD 分离 worker,parallel_config属性则汇总出完整的 TP/PP/EP/MoE-DP 配置,用于后续训练侧拓扑推导。

参数填充与拓扑推导

apply_external_engine_info_to_args(external.py)将发现结果写回参数对象:

  • args.rollout_external_engine_infos:引擎信息字典列表;
  • args.rollout_num_engines:外部引擎总数;
  • args.rollout_num_gpus:所有引擎 GPU 数量之和。

test_external_sglang_engines.py 中test_apply_external_engine_info_handles_pd展示了 PD 分离场景的完整链路:传入prefill:10090decode:10091两个地址后,rollout_num_gpus会被正确推导为2 + 4 = 6,且 worker 类型分别为prefilldecode,prefill 引擎的disaggregation_bootstrap_port也被保留。同文件中test_discover_external_engines_reads_server_info则验证了tp_size=4, pp_size=2的引擎会被推导为 8 块 GPU。

服务组与路由器接线

start_external_rollout_servers(external.py)完成最终接线:

  1. 调用start_router启动(或复用)路由器,并传入has_pd_disaggregation标记;
  2. 为每个外部引擎创建一个SGLangEngineRay Actor(num_cpus=0.2num_gpus=0,不占用训练作业的 GPU 配额);
  3. 按引擎 GPU 数累积engine_gpu_countsengine_gpu_offsets,用于后续的全局 GPU 编号编排;
  4. (router_ip, router_port)写入args.sglang_router_ip/args.sglang_router_port,并以default为模型名注册sglang_model_routers
  5. 返回以default为键的ExternalRolloutServer,其engine_parallel_configs保留了每个引擎的完整并行配置。

值得注意的是,ExternalRolloutServer.recover()只记录一条警告日志——外部引擎不参与 slime 的容错恢复,因为它们的生命周期属于外部部署系统(详见下文部署清单)。

--sglang-config的关系:互斥的边界划分

--rollout-external-engine-addrs--sglang-config互斥的,因为它们拥有不同的所有权边界:

  • --sglang-configslime 拥有引擎生命周期。YAML 描述拓扑,slime 负责启动服务器组、路由器、多模型服务,并做选择性权重更新。
  • --rollout-external-engine-addrs外部系统拥有引擎生命周期。slime 只发现已运行的引擎、将其挂接到路由器上,并把它们当作默认的 rollout 模型。

如果核心需求是多模型服务、冻结的参考/奖励模型、PD 分离或异构组配置,优先选择--sglang-config;只有当引擎已经部署在训练作业之外时,才使用外部引擎模式。

这一互斥关系在 slime/backends/sglang_utils/arguments.py 的参数校验中也有体现:当设置了rollout_external(外部引擎模式)时,若同时配置了prefill_num_serverssglang_config,会触发冲突校验。

环境与硬件解耦:外部引擎的核心收益

外部引擎模式最重要的隐含能力是环境解耦:SGLang 服务侧不需要使用 slime 训练作业的 Python 环境、Megatron 环境或 Ray 运行时。它可以在独立的 SGLang 容器、独立集群或其他编排系统中运行。slime 只依赖三样东西:

  1. HTTP 端点本身;
  2. /server_info发现接口;
  3. 所选权重同步传输方式所需的通信路径。

磁盘传输:允许异构 GPU 硬件

使用磁盘传输时,权重通过共享文件系统上的 HF checkpoint 或 safetensors delta 流动,SGLang 通过update_weights_from_disk热加载。这条路径不要求训练 GPU 与 rollout GPU 是同一型号,甚至不要求同一厂商——只要 SGLang 支持目标硬件后端、模型格式与精度配置即可。例如:训练跑在一个 GPU 集群上,rollout 服务跑在另一个 GPU 型号或厂商的集群上。

NCCL 传输:保持传统约束

使用 NCCL 传输时,NCCL 通信与硬件兼容性的常规要求仍然适用。对于跨厂商、网络不互通或跨数据中心的部署,优先选择--update-weight-transport disk

权重更新路径总览

权重同步的两种策略由 slime/utils/arguments.py 中的两个参数共同决定:

参数取值含义
--update-weight-modefull(默认)/deltafull每次同步广播所有参数;delta对上一次同步的 CPU 快照做 diff,只传输变化字节(仅磁盘传输)
--update-weight-transportnccl(默认)/disk权重同步的载体;full模式下 NCCL 广播分块、磁盘写入完整 HF checkpoint 后由引擎重载;delta模式仅支持磁盘

参数校验逻辑(arguments.py)进一步约束了组合方式:

  • --update-weight-transport=disk必须配合--update-weight-disk-dir,指向训练器与 rollout 引擎共享的文件系统,否则报错;
  • --update-weight-mode=delta必须搭配--update-weight-transport=disk
  • --update-weight-mode=delta--colocate互斥——colocate 场景通过 CUDA IPC 句柄跨进程传输权重,delta 的记账(快照 + diff + 编码)是纯开销;
  • --update-weight-mode=delta必须配置--update-weight-local-checkpoint-dir(详见下文)。

更新方式一:从磁盘全量更新(Update From Disk)

全量 checkpoint 磁盘更新是外部部署最简单、最稳妥的回退路径:

--update-weight-mode full --update-weight-transport disk --update-weight-disk-dir /shared/fs/full-updates

工作流程:每次权重同步时,训练器在--update-weight-disk-dir下写入一个完整的 HF checkpoint 目录(例如weight_v000123/),然后通过 HTTP 调用每个 SGLang 引擎的update_weights_from_disk端点,让引擎在不重启进程的情况下重新加载 checkpoint。

该流程的实现位于 slime/backends/megatron_utils/update_weight/update_weight_from_disk.py 中的UpdateWeightFromDisk类——从源码看,它通过save_hf_model_to_path落盘 checkpoint,并为每次同步维护weight_version递增版本号。该实现还支持--custom-update-weight-post-write-path钩子(arguments.py):对对象存储等非 POSIX 文件系统而言,跨主机读后写一致性无法自动保证,训练器各 rank 写完文件后需要显式发布(例如上传到后端对象存储),引擎才能看到写入。

本地缓存:从"每 rank 一次读"到"每主机一次读"

增加--update-weight-local-checkpoint-dir后,每个引擎会先把已发布的 checkpoint 拉取到其覆盖的每一台主机的本地磁盘(例如 NVMe),再从本地加载:

  • 拉取动作通过/pull_weights端点完成(该端点由 slime 的 sglang patch 提供);
  • 收益是每个主机只做一次共享文件系统读取,而不是每个 rank 读一次;
  • 当共享目录由对象存储支撑、或引擎横跨多个节点时,这一差异非常关键。

--update-weight-local-checkpoint-dir的完整语义在 arguments.py 中有详细说明:对 delta 模式必需,对全量磁盘同步可选(配置后引擎改为先拉取到本地再加载,而不是直接读共享目录)。

调试辅助

--update-weight-disk-keep-files

该参数(arguments.py)会跳过全量 checkpoint 目录的清理,在引擎确认加载完成之后仍保留这些目录,便于排查加载异常或做离线校验。

该模式的定位:控制面简单——不需要训练器与引擎之间的 NCCL 组,双方只需看到同一个共享文件系统路径。代价是体积:每次同步都写入完整的 Actor 权重,对大型模型或高频更新而言开销较大。

更新方式二:Delta 增量更新(Update With Delta)

Delta 更新面向大型模型跨集群、跨数据中心的训练/推理拆分场景。与每次同步都写全量 checkpoint 不同,训练器维护上一轮同步的CPU 快照,对每个参数与快照做 diff,只发布变化字节;每个引擎的/pull_weights端点(slime 的 sglang patch 提供)在其覆盖的每台主机上把 delta 应用进主机本地 checkpoint,随后引擎通过原生的update_weights_from_disk端点重载。slime 只调用引擎的 HTTP 端点,因此多节点外部引擎与 slime 自启动引擎在权重同步上的行为完全一致。

--update-weight-mode delta --update-weight-transport disk --update-weight-disk-dir /shared/fs/delta-updates --update-weight-local-checkpoint-dir /local/nvme/rollout-ckpt

delta 模式的实现位于 slime/backends/megatron_utils/update_weight/update_weight_from_disk_delta.py,其机制、编码、完整性校验与共享文件系统可见性钩子,详见 Delta Weight Sync。

两个可选的底层调优参数

在 arguments.py 中,delta 模式还暴露了两个底层参数,引擎会从每个版本的 index 元数据中读取选择:

  • --update-weight-delta-encodingxor默认 /overwrite):
    • xor新值 ^ 旧值,线缆体积最小、速度最快,但它是自逆操作,必须基于正确基线恰好应用一次(应用两次会还原回去);
    • overwrite:只写变化位置 + 新的绝对值,体积更大但幂等,可任意次数重放。
    • 两者都是字节级、与 dtype 无关。
  • --update-weight-delta-checksumxxh3-128默认 /blake3/adler32):
    • 每个张量的完整性校验和;由于应用过程受解压 + XOR 主导,这不是速度选择而是摘要属性选择;
    • xxh3-128:最快的非加密摘要,意外损坏碰撞概率可忽略;
    • blake3:加密摘要,适用于不可信存储;
    • adler32:32 位,用于与期望该格式的系统互通。

部署检查清单

外部引擎部署是否就绪,逐项核对以下要点(源自原文档并补充源码验证):

  • 网络可达:外部引擎的 HTTP 地址必须能从训练作业所在节点访问(get_server_info默认超时 30 秒,见 external.py)。
  • 环境独立:外部引擎可以使用独立的 SGLang 环境,不需要 slime 或 Megatron 训练环境。
  • 硬件异构可行:磁盘传输支持训练与 rollout 使用不同 GPU 型号或厂商,前提是 SGLang 支持目标硬件与模型格式。
  • 共享路径是硬前提:磁盘传输要求训练器与 SGLang 引擎看到同一个--update-weight-disk-dir路径;只对训练器可见的路径是不够的,参数校验会直接报错(arguments.py)。
  • 容错边界:外部引擎不会被 slime 的故障恢复机制接管(ExternalRolloutServer.recover()仅记录警告并跳过,见 external.py);其生命周期属于外部部署系统。
  • 参数互斥--sglang-config--rollout-external-engine-addrs互斥,不可同时使用。
  • delta 与 colocate 互斥:delta 模式不支持--colocate,因为 colocate 同步走 CUDA IPC 句柄,delta 编码并不能减少实际传输量(校验逻辑见 arguments.py)。

相关背景:训练/推理拆分下的权重同步趋势

值得留意的是,外部引擎、磁盘全量更新与 delta 磁盘传输所解决的问题,也是业界在大规模 RL 推理基础设施中普遍面临的课题:一旦训练与推理解耦,权重同步就必须跨进程、跨集群乃至跨数据中心工作,同时不能让全量模型传输主导训练循环。slime 提供的这条"外部引擎 + disk 传输"路径,正是对这一基础设施问题的工程化回答:训练侧只依赖 HTTP 端点与共享文件系统,权重以全量 checkpoint 或增量 delta 两种粒度流动,配合/pull_weights本地缓存与自定义发布钩子,适配从单集群到对象存储支撑的跨数据中心场景。

总结

外部 Rollout 引擎模式是 slime 在训练/推理拆分架构下的关键连接能力:通过--rollout-external-engine-addrs只接入不接管,通过磁盘传输实现环境与硬件解耦,通过全量/增量两种权重更新模式在"简单可靠"与"跨集群高效"之间取得平衡。选择路径时可遵循三条主线:引擎生命周期归属决定用--sglang-config还是外部引擎;NCCL 组是否可建立决定传输方式;模型规模与同步频率决定用全量还是 delta。结合本文的源码分析与部署清单,你可以为独立推理集群、跨厂商 GPU 或跨数据中心等真实部署场景快速落地一套可运行的权重同步方案。

【免费下载链接】slimeslime is an LLM post-training framework for RL Scaling.项目地址: https://gitcode.com/GitHub_Trending/slime12/slime

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询