Skip to content

[3/n] Disaggregated rollout: engine-side /pull_weights#2181

Merged
zhuzilin merged 1 commit into
THUDM:mainfrom
modal-projects:delta-pull-weights
Jul 7, 2026
Merged

[3/n] Disaggregated rollout: engine-side /pull_weights#2181
zhuzilin merged 1 commit into
THUDM:mainfrom
modal-projects:delta-pull-weights

Conversation

@nanjiangwill

@nanjiangwill nanjiangwill commented Jul 6, 2026

Copy link
Copy Markdown
Collaborator

Series:

  1. [1/n] Disaggregated rollout: delta weight sync (disk + NCCL transports) #1806
  2. [2/n] Disaggregated rollout: disk-level delta weight sync #2089
  3. [3/n] Disaggregated rollout: engine-side /pull_weights #2181

#2089 fanned the per-host delta apply out from slime via Ray (all_engine_actors) because only node 0 of a multi-node engine has an HTTP server — leaking engine topology into slime and breaking for external engines.

This PR moves the pull into the engine: POST /pull_weights {local_checkpoint_dir, source_dir, target_version} syncs the host-local checkpoint on every host the engine spans (standalone docker/patch/latest/sglang-pull_weights.patch; sglang.patch untouched). slime talks to one endpoint per engine.

  • Fan-out rides the existing scheduler broadcast; a per-host flock dedups ranks; the reply is all-gathered, so success ⇔ every host verified.
  • A published weight_v{N:06d}/ is self-describing: full HF checkpoint (copied, resets the chain) or delta (in-place, per-tensor checksums). Fresh hosts seed from the newest full version ≤ target, or the engine's model_path.
  • Non-POSIX shared-filesystem visibility hooks: --custom-update-weight-post-write-path (trainer, after write) / --custom-pull-weights-pre-read-hook (engine, before read).
  • slime: all_engine_actors and sync_local_checkpoint removed; full-mode disk sync also pulls to local disk when --update-weight-local-checkpoint-dir is set; two non-POSIX full-disk publisher bugs fixed (per-rank mkdir/rename, per-rank hook).

Validation — GLM-4.7-Flash, 2 trainer nodes + one 2-node tp16 engine, object-store-backed shared filesystem, 3 rollouts per mode; plus an offline suite (mixed streams, resharded resets, pruned history, corruption, concurrency).

delta(disk) full(disk)
pulls 4/4 (v0 seed + v1–v3) 4/4 (v1–v4)
pulls per host per version 1 1
bytes per sync 0.6–0.8 GB (0.3–0.4% density) ~60 GB
update_weights time 17–55 s 158–371 s
checksum / size failures 0 0
trainer↔rollout logprob abs diff 0.039–0.041 0.039–0.041

The logprob diff already measures 0.041 at rollout 0, before any sync (engine serving its init-loaded checkpoint) — that residual is sglang-vs-Megatron kernel numerics, and the syncs add nothing on top of it.

@nanjiangwill nanjiangwill changed the title Delta disk sync: move the per-host apply into the engine (/pull_weights) Disk weight sync: engines pull published weights on every host (/pull_weights) Jul 6, 2026
@nanjiangwill
nanjiangwill force-pushed the delta-pull-weights branch 3 times, most recently from ab04422 to 42037c8 Compare July 6, 2026 18:46
@nanjiangwill nanjiangwill changed the title Disk weight sync: engines pull published weights on every host (/pull_weights) Disk weight sync via engine-side /pull_weights Jul 6, 2026
@nanjiangwill nanjiangwill changed the title Disk weight sync via engine-side /pull_weights [3/n] Disaggregated rollout: engine-side /pull_weights Jul 6, 2026
@nanjiangwill
nanjiangwill force-pushed the delta-pull-weights branch 3 times, most recently from 8217c60 to 9a05693 Compare July 6, 2026 19:05
…_weights)

Follow-up to THUDM#2089. That PR fanned the host-local delta apply out from slime via Ray (all_engine_actors, one actor per host of each multi-node engine) because only node 0 of a multi-node engine has an HTTP server. That leaks engine topology into slime and cannot work for external rollout engines, where slime only has an endpoint.

A new /pull_weights endpoint (shipped as the standalone docker/patch/latest/sglang-pull_weights.patch) has each engine pull the published weights onto every host it spans, riding the existing control-request broadcast; a per-host flock collapses co-located ranks to one pull, and the reply is all-gathered across the TP group so success means every host holds a verified checkpoint. The pull is artifact-driven: a published version is either a full HF checkpoint (copied as-is, resetting the chain) or a delta against its predecessor (patched in place, per-tensor checksums), detected from the index metadata; a fresh host seeds from the newest full version at or below the target, or from the engine's own model path for a pure-delta stream. The shared-filesystem refresh hook follows sglang's custom-weight-loader convention (--custom-pull-weights-pre-read-hook), forwarded through the existing --sglang-* passthrough.

slime now only talks to one endpoint per engine: all_engine_actors and SGLangEngine.sync_local_checkpoint are removed, the delta updater calls pull_weights(v) before the reload, and pull_weights(0) during baseline capture replaces the init-thread base materialization (still overlapped with the snapshot gather). Full-mode disk sync pulls to local disk too when --update-weight-local-checkpoint-dir is set. The post-write hook is renamed --custom-update-weight-post-write-path since it now serves full and delta alike, and two pre-existing full-disk bugs on non-POSIX shared filesystems are fixed: every writing rank creates the version dir and renames its own shards, and the post-write hook runs on every rank.

Validated end to end on GLM-4.7-Flash non-colocated (2 trainer nodes + one 2-node tp16 rollout engine, object-store-backed shared filesystem): delta mode 4/4 pulls with 0 checksum mismatches (~23s steady-state sync); full mode 4/4 pulls, one pull per host per version, engines reloading from the pulled local checkpoint.
@zhuzilin
zhuzilin merged commit 474861a into THUDM:main Jul 7, 2026
40 checks passed
nanjiangwill added a commit to nanjiangwill/sglang that referenced this pull request Jul 7, 2026
…host-local checkpoint

A trainer publishes each weight sync as a version directory (a full HF
checkpoint, or zstd-compressed per-tensor deltas with checksums) under a
shared source_dir. /pull_weights fans out to every rank on every node of
the deployment; each host seeds a local checkpoint from the newest full
version (or the server's own model path) and applies the delta chain in
place, verified per-tensor. The engine then reloads the local checkpoint
through the ordinary update_weights_from_disk path, so the weight-loading
code never sees the delta format.

--custom-pull-weights-pre-read-hook covers object-store-backed shared
filesystems that need an explicit refresh before reads.

Ported from slime's runtime patch (THUDM/slime#2181) for miles/slime-style
disaggregated RL training.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KLdXoApPFW7oYmN8yEPHhz
nanjiangwill added a commit to nanjiangwill/sglang that referenced this pull request Jul 7, 2026
…host-local checkpoint

A trainer publishes each weight sync as a version directory (a full HF
checkpoint, or zstd-compressed per-tensor deltas with checksums) under a
shared source_dir. /pull_weights fans out to every rank on every node of
the deployment; each host seeds a local checkpoint from the newest full
version (or the server's own model path) and applies the delta chain in
place, verified per-tensor. The engine then reloads the local checkpoint
through the ordinary update_weights_from_disk path, so the weight-loading
code never sees the delta format.

--custom-pull-weights-pre-read-hook covers object-store-backed shared
filesystems that need an explicit refresh before reads.

Ported from slime's runtime patch (THUDM/slime#2181) for miles/slime-style
disaggregated RL training.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KLdXoApPFW7oYmN8yEPHhz
nanjiangwill added a commit to nanjiangwill/sglang that referenced this pull request Jul 7, 2026
…host-local checkpoint

A trainer publishes each weight sync as a version directory (a full HF
checkpoint, or zstd-compressed per-tensor deltas with checksums) under a
shared source_dir. /pull_weights fans out to every rank on every node of
the deployment; each host seeds a local checkpoint from the newest full
version (or the server's own model path) and applies the delta chain in
place, verified per-tensor. The engine then reloads the local checkpoint
through the ordinary update_weights_from_disk path, so the weight-loading
code never sees the delta format.

--custom-pull-weights-pre-read-hook covers object-store-backed shared
filesystems that need an explicit refresh before reads.

Ported from slime's runtime patch (THUDM/slime#2181) for miles/slime-style
disaggregated RL training.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KLdXoApPFW7oYmN8yEPHhz
nanjiangwill added a commit to nanjiangwill/sglang that referenced this pull request Jul 7, 2026
…host-local checkpoint

A trainer publishes each weight sync as a version directory (a full HF
checkpoint, or zstd-compressed per-tensor deltas with checksums) under a
shared source_dir. /pull_weights fans out to every rank on every node of
the deployment; each host seeds a local checkpoint from the newest full
version (or the server's own model path) and applies the delta chain in
place, verified per-tensor. The engine then reloads the local checkpoint
through the ordinary update_weights_from_disk path, so the weight-loading
code never sees the delta format.

--custom-pull-weights-pre-read-hook covers object-store-backed shared
filesystems that need an explicit refresh before reads.

Ported from slime's runtime patch (THUDM/slime#2181) for miles/slime-style
disaggregated RL training.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KLdXoApPFW7oYmN8yEPHhz
nanjiangwill added a commit to nanjiangwill/sglang that referenced this pull request Jul 7, 2026
…host-local checkpoint

A trainer publishes each weight sync as a version directory (a full HF
checkpoint, or zstd-compressed per-tensor deltas with checksums) under a
shared source_dir. /pull_weights fans out to every rank on every node of
the deployment; each host seeds a local checkpoint from the newest full
version (or the server's own model path) and applies the delta chain in
place, verified per-tensor. The engine then reloads the local checkpoint
through the ordinary update_weights_from_disk path, so the weight-loading
code never sees the delta format.

--custom-pull-weights-pre-read-hook covers object-store-backed shared
filesystems that need an explicit refresh before reads.

Ported from slime's runtime patch (THUDM/slime#2181) for miles/slime-style
disaggregated RL training.
nanjiangwill added a commit to nanjiangwill/sglang that referenced this pull request Jul 7, 2026
…host-local checkpoint

A trainer publishes each weight sync as a version directory (a full HF
checkpoint, or zstd-compressed per-tensor deltas with checksums) under a
shared source_dir. /pull_weights fans out to every rank on every node of
the deployment; each host seeds a local checkpoint from the newest full
version (or the server's own model path) and applies the delta chain in
place, verified per-tensor. The engine then reloads the local checkpoint
through the ordinary update_weights_from_disk path, so the weight-loading
code never sees the delta format.

--custom-pull-weights-pre-read-hook covers object-store-backed shared
filesystems that need an explicit refresh before reads.

Ported from slime's runtime patch (THUDM/slime#2181) for miles/slime-style
disaggregated RL training.
@nanjiangwill
nanjiangwill deleted the delta-pull-weights branch July 7, 2026 18:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants