feat: colocated online training with in-process SGLang capture - #783
Draft
maocheng23 wants to merge 1 commit into
Draft
feat: colocated online training with in-process SGLang capture#783maocheng23 wants to merge 1 commit into
maocheng23 wants to merge 1 commit into
Conversation
5 tasks
This was referenced Sep 1, 2026
maocheng23
force-pushed
the
maocheng/colocate-3-rank0-tracker
branch
from
September 1, 2026 23:30
48a2e3e to
fb2bd50
Compare
maocheng23
force-pushed
the
maocheng/colocate-4-online-core
branch
from
September 1, 2026 23:30
f1340a8 to
86e884c
Compare
maocheng23
changed the base branch from
maocheng/colocate-3-rank0-tracker
to
maocheng/colocate-1-capture-rows
September 1, 2026 23:31
Every trainer rank loads one SGLang target shard next to its FSDP draft shard and captures hidden states in process. The colocated path is a structural peer of the disaggregated one: - specforge/training/colocated.py assembles the run (mirrors disaggregated.py); build_training_run only dispatches by topology. - specforge/training/prompt_plan.py is the one online prompt planner: the producer's per-epoch permutation, with target-DP islands taking strided, equal, batch-aligned shards. Colocated and disaggregated runs over the same prompts and seed see the same sample identities. - LocalRolloutStream pulls one target batch per trainer request from the lazy prompt stream (no eager multi-epoch expansion) and stages at most one local batch; TP peers capture the same batch and train disjoint slices. - launch_plan.resolve_sglang_engine_args is shared by the external-server CLI renderer and the in-process engine kwargs. - Rank-coordinated prompt-cache preparation and the lazy vocab-map builder live in assembly.py under topology-neutral names. - configure_flex_attention_inductor lives in torch_compat and is scoped to colocated runs.
maocheng23
force-pushed
the
maocheng/colocate-1-capture-rows
branch
from
September 2, 2026 00:24
c4778db to
68cf3fc
Compare
maocheng23
force-pushed
the
maocheng/colocate-4-online-core
branch
from
September 2, 2026 00:24
86e884c to
0670a4e
Compare
Base automatically changed from
maocheng/colocate-1-capture-rows
to
maocheng/colocate-3-rank0-tracker
September 2, 2026 04:27
Base automatically changed from
maocheng/colocate-3-rank0-tracker
to
maocheng/colocate-2-teardown-abort
September 2, 2026 04:33
Collaborator
Author
|
GPU validation on sglang 0.5.18 (B300, this branch merged onto main
Per-rank time split from the observability records: capture 48% / draft compute 52% (tp1) and 54% / 46% (tp2); trainer bubble < 0.4%. So the two open GPU gates listed in the description — 0.5.18 tp=1 smoke and a tp>=2 island run — have now been exercised; the 4x8 HSDP run for #784 is still open. Two things noticed while running it (not blockers): with a pre-tokenized JSONL prompt source every rank re-parses the file while rank 0 holds the coordination collective (the 40k-row file took ~4 min before step 1), and TP2 islands add ~2 min of extra SGLang/JIT startup versus tp1. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation
Stack 4/5 replacing draft #766 — the colocated online runtime itself. SpecForge online training currently requires a disaggregated producer/consumer topology even when target capture and draft training fit on the same accelerator, adding feature serialization, transport, and a second GPU pool. This PR adds a bounded colocated path: every trainer rank owns its local SGLang target shard and FSDP draft shard, captures one target batch on demand, trains its rank-local slice, and releases it before the next capture.
Design goal for this cut: colocated is a structural peer of disaggregated, and the disaggregated path is not changed. Every shared-path touch is listed under "Shared paths" below.
Structure
training/disaggregated.py::build_disaggregated_runtraining/colocated.py::build_colocated_runassembly.build_training_run_with_run_logger,_build_offline_colocated_run)training/prompt_plan.py: same per-epoch permutation and task ids; islands take strided, equal, batch-aligned shards → colocated vs disaggregated runs over the same prompts/seed are comparable at matched samplesmodel.sglang_*→ engine argslaunch_plan._sglang_argvlaunch_plan.resolve_sglang_engine_args(CLI renderer and in-process kwargs are two views of one resolution)SGLangServerCaptureAdapter(Mooncake)LocalSGLangCaptureAdapteroverOfflineSGLangCaptureBackend.capture_rows(#780)StreamingRefQueueLocalRolloutStream: pull-through, lazy prompt stream, stages at most one local batchlaunch._assemble_trainerbuild_disagg_online_*build_colocated_online_runtime(now inlaunch.__all__; five builders as ARCHITECTURE.md states)Modifications
deployment.mode: local_colocatedvalidates for online runs; colocated checks cover context-length headroom, request/token capacity versustp_size * batch_size, SGLang DP/EP constraints, and the sp=1 limitation. Disaggregated/offline validation is unchanged.training.tp_sizebecomes the target-TP island width. TP peers capture one aligned TP-wide batch and train disjoint local slices (each peer clones only its slice to release the packed capture allocation); islands are target-DP replicas with disjoint prompt shards.LocalRolloutStreamingests exactly one target batch per trainer request from the lazy prompt stream (no eager multi-epoch expansion), fails loud on a short tail or a partial capture, and reports interval capture time/throughput plus peak staged features throughperf/*.prompt_plan, seed, epochs, island count, dataset size, batch/TP sizes); any recorded value that differs raises instead of silently training the wrong slice (a bug in feat: add scalable colocated online training #766). The consumed prefix is skipped lazily.assembly._prepare_prompts_coordinated, generic name and docstring) prevents a tokenization process storm and Arrow-cache write races. The EAGLE3 vocab-map builder (_install_dataset_vocab_mapping) now takes a lazy counter and skips the corpus walk on a cache hit (offline benefits too).torch_compat.configure_flex_attention_inductorpins the inductor GEMM candidates toATEN,TRITONfor colocated FlexAttention runs only; the docstring states what was observed and that the mechanism is not isolated (torch 2.11's default already listsATEN).colocated_training.md(quick-start path fixed, prompt-plan and pull-through sections), topology matrix,DESIGN.mdqueue contract (loader_prefetch_safe), recipe underexamples/configs/online/colocated/.Shared paths touched (behavior for disaggregated/offline)
controller.py:del batchafter the micro-step (reference release only);perf/global_samples_per_secondusesworld // sp_size(identical wheretp_size=1, which disaggregated/offline enforce); additive peak-memory metrics and an optionalruntime_metrics_provider(Nonefor disaggregated).feature_dataloader.py: honors a queue'sloader_prefetch_safe = False(defaultTrue),del batchafter yield.trainer.py/launch._assemble_trainer:clone_on_fetchthreaded through, defaultTrue.launch.py: the producer's prompt planner moved totraining/prompt_plan.pyunchanged (import-only change);disaggregated.pyuses the sharedonline_prompt_seed.launch_plan._sglang_argvrenders fromresolve_sglang_engine_args; output identical.model_providers.py:needs_target_headincludes onlinelocal_colocated.Related Issues
Splits #766 (supersedes it together with the rest of the stack). Stack: #781 ← #782 ← #780 ← #4 (this) ← #784 hybrid-shard.
Accuracy Test
tp_size=1only, from the feat: add scalable colocated online training #766 run on sglang 0.5.14 (Qwen3-8B DSpark, 90 optimizer steps / 360 samples on 4x H200, finite loss and grad norms, sequence lengths 43–3911 under a 4096 cap). This rebase moves the in-process engine to sglang 0.5.18; the smoke run must be repeated before this leaves draft, and target TP > 1 islands have not been executed on hardware yet (design + CPU tests only). Both are tracked in the checklist.tests/test_config tests/test_runtime tests/test_optimizerhas the same failure set asmain(pre-existing CUDA/sglang-environment failures), plustest_sglang_capture_hooks.pywhich needs sglang (CI). New coverage intest_colocated_online.py: shared planner (island shards partition the producer permutation, epoch task ids match the producer), coordinated cache preparation, run assembly (engine sizing, plan metadata, resume mismatch/prefix/completed), adapter layout and TP-slice detachment,LocalRolloutStreamdriven through the realRolloutWorker+LocalFeatureStore+ adapter at TP=2 in lockstep (disjoint slices, bounded staging, clean status), builder wiring into_assemble_trainer; plustest_sglang_engine_args.pyandtest_torch_compat.py.Benchmark & Profiling
From the #766 run (Qwen3-8B, DSpark, BF16, SGLang 0.5.14 local capture,
SHARD_GRAD_OP, batch 1/rank, 4x H200): 22.93 samples/s steady-state (steps 50–90), 12.94 samples/s including cold start; post-compilation capture ≈11.2% of step wall time; peak 31.94/35.07 GiB allocated/reserved per rank; peak staged features 0.179 GiB. To be refreshed on 0.5.18.Checklist
black --checkandisort --check-only).