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
Every trainer rank loads one SGLang target shard next to its FSDP draft shard and captures hidden states in process, removing the feature serialization, transport, and second GPU pool that the disaggregated topology requires when target and draft fit on the same accelerator. - deployment.mode=local_colocated now validates for online runs; typed colocated checks cover context-length headroom, request/token capacity, SGLang DP/EP constraints, and the sp=1 limitation. - build_colocated_online_runtime assembles a bounded pull-through LocalRolloutStream: the trainer requests one batch, the local worker captures it synchronously via the offline backend's capture_rows, and the rank-private in-memory LocalFeatureStore holds at most one training batch. The loader skips its defensive clone and stays synchronous. - training.tp_size becomes the target-TP island width: contiguous TP peers capture one aligned TP-wide batch and train disjoint local slices; target-DP islands receive deterministic disjoint prompt plans with per-epoch truncation to complete TP-wide batches, checkpoint preposition on resume, and a hard error when a checkpoint's plan parameters do not match the current config. - Rank zero populates the tokenized prompt cache before peers read it (node-local caches build once per node), preventing a preprocessing process storm and Arrow cache write races. - Colocated runs keep TorchInductor's ATen fallback available for variable-length FlexAttention shapes that otherwise raise NoValidChoicesError; explicit environment overrides stay authoritative. - perf/* gains capture time/throughput, feature-residency peaks, and accelerator peak-memory at each log interval; global samples/s counts target-TP peers as sample-parallel. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
5 tasks
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 on demand, trains its rank-local feature slice, and releases it before the next capture.
Compared with #766, this cut deliberately drops several pieces to keep the change minimal (details in the stack summary): no
deployment.colocatedconfig knobs (synchronize_after_capture/zero_copy_featuresare hardcoded to the validated safe defaults), no global FlexAttention default-backend change (SPECFORGE_FLEX_ATTENTION_BACKENDalready exists for opting into FLASH on Blackwell), noCaptureConfig.extrafeature-name plumbing on the shared disaggregated path, and the TorchInductor ATen-fallback fix is scoped to the colocated branch instead of everyspecforge traininvocation.Modifications
deployment.mode: local_colocatednow validates 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.build_colocated_online_runtimeassembles a synchronous, bounded pull-throughLocalRolloutStream(single worker): the trainer requests one batch insideFeatureDataLoader.get(), the localRolloutWorkercaptures via the offline backend'scapture_rowsthrough the newLocalSGLangCaptureAdapter, and the rank-private in-memoryLocalFeatureStoreis bounded to one training batch. The loader disables prefetch threads (loader_prefetch_safe) and skips the defensive clone; the controller and loader release the previous batch before requesting the next so long-context features never overlap.training.tp_sizebecomes the colocated target-TP island width. Contiguous 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); target-DP islands receive deterministic disjoint prompt plans with per-epoch truncation to complete TP-wide batches.dataset_size/batch_size/tp_sizedo not match the current plan now raises instead of silently training nothing (a bug in feat: add scalable colocated online training #766).NoValidChoicesError(torch's own suggested remedy); an explicitTORCHINDUCTOR_MAX_AUTOTUNE_GEMM_BACKENDSstays authoritative.perf/*gains capture time/throughput, feature-residency peaks, and accelerator peak-memory at each log interval;perf/global_samples_per_secondcounts target-TP peers as sample-parallel (unchanged for tp=1 topologies).colocated_training.md, topology matrix updates, and the reservedexamples/configs/online/colocated/directory gets the Qwen3-8B DSpark 8xH200 recipe.Related Issues
Splits #766 (supersedes it together with the rest of the stack). Stack: #1 capture-rows ← #2 teardown-abort ← #3 rank0-tracker ← #4 (this) ← #5 hybrid-shard.
Accuracy Test
From the #766 validation run (same runtime semantics; this restructuring hardcodes the two policy defaults that run used):
NoValidChoicesError.main(pre-existing CUDA/sglang-environment failures only); new coverage intest_colocated_online.py(prompt planning disjointness/TP alignment, TP-slice detachment, bounded residency, resume-mismatch rejection, prompt-cache coordination),test_torch_environment.py, launch-plan and schema tests.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 rank-local feature residency 0.179 GiB.Checklist
black --checkandisort --check-only).