Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
9a2fde3
feat(runtime): add bounded windowed capture scheduling
heiheiha798 Jul 17, 2026
6e700ce
perf(dflash): combine key value projection inputs
heiheiha798 Jul 17, 2026
4924765
perf(dflash): add fused frozen-head cross entropy
heiheiha798 Jul 17, 2026
89707b6
perf(training): add fused AdamW backend
heiheiha798 Jul 17, 2026
f5c69d9
perf(benchmarks): add consumer critical path measurements
heiheiha798 Jul 17, 2026
d6b9857
feat(runtime): integrate windowed capture services
heiheiha798 Jul 17, 2026
4ce5d01
feat: wire local capture into windowed fanout
heiheiha798 Jul 17, 2026
33f9708
perf(dflash): add configurable fused draft kernels
heiheiha798 Jul 17, 2026
d3b1743
perf(dflash): compact zero-weight frozen CE rows
heiheiha798 Jul 17, 2026
bd46b9f
perf(dflash): expose FlexAttention kernel options
heiheiha798 Jul 17, 2026
989ec29
perf(runtime): coalesce windowed producer capture batches
heiheiha798 Jul 17, 2026
64eadc0
fix(capture): harden server and Mooncake lifecycle
heiheiha798 Jul 17, 2026
2dff16f
fix(runtime): preserve durable Mooncake cleanup after restack
heiheiha798 Jul 18, 2026
4fac7bd
fix(disagg): preserve unified capture retry lifecycle
heiheiha798 Jul 18, 2026
de1bb00
feat(observability): add role-aware NVML telemetry
heiheiha798 Jul 17, 2026
8607cb5
feat(runtime): package production DFlash fanout
heiheiha798 Jul 17, 2026
6a9331f
feat(runtime): expose consumer input pipeline timings
heiheiha798 Jul 17, 2026
9b1a4f5
feat(runtime): report window demand wait metrics
heiheiha798 Jul 17, 2026
b90ec53
perf(runtime): roll prefetch through capture windows
heiheiha798 Jul 17, 2026
37ca292
fix(observability): allow managed worker descendants
heiheiha798 Jul 17, 2026
b7ca5e5
fix(benchmarks): run against the active checkout
heiheiha798 Jul 18, 2026
938f1e9
docs(benchmarks): show single-GPU invocation
heiheiha798 Jul 18, 2026
60ad0d3
fix(dflash): wire optimized backends through unified runtime
heiheiha798 Jul 18, 2026
364ca26
fix(benchmarks): use unified algorithm and loader APIs
heiheiha798 Jul 18, 2026
cb313c2
fix(runtime): keep fanout behind canonical package surfaces
heiheiha798 Jul 18, 2026
82fb49e
style: satisfy pre-commit after restack
heiheiha798 Jul 18, 2026
1602eb4
fix(capture): migrate prior server patch revisions
heiheiha798 Jul 18, 2026
57ed167
fix(fanout): honor managed Mooncake endpoints
heiheiha798 Jul 18, 2026
909bf78
fix(runtime): align windowed ACK ownership
heiheiha798 Jul 18, 2026
f85c694
fix(ci): pass capture patch interpreter
heiheiha798 Jul 18, 2026
b7b0825
fix(ci): align live capture gate ownership
heiheiha798 Jul 18, 2026
d90a30d
fix(observability): harden GPU telemetry evidence
heiheiha798 Jul 18, 2026
02103f8
fix(runtime): harden window recovery and child cleanup
heiheiha798 Jul 18, 2026
535998e
fix(mooncake): make deferred cleanup complete and bounded
heiheiha798 Jul 18, 2026
937e8b0
fix(config): validate fanout runtime boundaries
heiheiha798 Jul 18, 2026
c325a93
test(dflash): cover real kernels and resume boundaries
heiheiha798 Jul 18, 2026
4e30abd
test(runtime): exercise legacy installer upgrades
heiheiha798 Jul 18, 2026
7371639
style(ci): satisfy server capture gate isort
heiheiha798 Jul 18, 2026
27f34fe
refactor: narrow fanout change to runtime scope
heiheiha798 Jul 18, 2026
9c226c7
feat(disagg): use canonical windowed fanout launch
heiheiha798 Jul 18, 2026
283f2d3
refactor(disagg): split windowed capture responsibilities
heiheiha798 Jul 18, 2026
6ebcbb2
fix(disagg): preserve physical generations across recapture
heiheiha798 Jul 18, 2026
3f274b9
refactor(sglang): collapse capture patch migration
heiheiha798 Jul 18, 2026
61455f9
docs(disagg): add canonical heterogeneous fanout example
heiheiha798 Jul 18, 2026
423dae9
test(ci): align fanout fixtures with current contracts
heiheiha798 Jul 19, 2026
cd9ce32
fix(mooncake): enforce the raw tensor wire path
heiheiha798 Jul 19, 2026
5864402
Merge upstream/main into feat/one-producer-multi-consumer-launcher
heiheiha798 Jul 20, 2026
ec07263
test(config): align unified recipe count
heiheiha798 Jul 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ jobs:
run: |
source sf/bin/activate
export PYTHONPATH=$PWD
bash scripts/apply_sglang_spec_capture_patch.sh
bash scripts/apply_sglang_spec_capture_patch.sh \
--python "$PWD/sf/bin/python" --apply
python -c 'import importlib.util, shutil, torch; assert torch.cuda.is_available(), "live capture gate requires CUDA"; assert importlib.util.find_spec("mooncake.store"), "live capture gate requires mooncake.store"; assert shutil.which("mooncake_master") or __import__("os").environ.get("MOONCAKE_MASTER_SERVER_ADDR"), "live capture gate requires mooncake_master"'
python -m unittest tests.test_runtime.test_server_capture_gate -v

Expand Down
51 changes: 49 additions & 2 deletions examples/configs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ training, `*-offline.yaml` consumes precomputed features, and
recipe is disaggregated even when its historical filename only says `online`.
VLM training is not supported, so the catalog contains text-only recipes.

The `qwen3-8b-dflash-1server-dp7-disaggregated.yaml`,
The `qwen3-8b-dflash-windowed-fanout.yaml`,
`qwen3-8b-dflash-1server-dp7-disaggregated.yaml`,
`qwen3-8b-domino-1server-dp7-disaggregated.yaml`,
`qwen3-8b-domino-multiserver-disaggregated.yaml`,
`qwen3.6-27b-dflash-1server-dp2-disaggregated.yaml`, and
Expand Down Expand Up @@ -114,6 +115,7 @@ assume the command runs from the repository root.
| Colocated offline | `qwen3-8b-eagle3-offline.yaml` |
| External-service online | `qwen3-8b-eagle3-disaggregated.yaml` |
| Managed-local disaggregated online | `qwen3-8b-domino-multiserver-disaggregated.yaml` |
| Independent heterogeneous consumers | `qwen3-8b-dflash-windowed-fanout.yaml` |
| Disaggregated offline | `qwen3-8b-eagle3-offline-disaggregated.yaml` |

The online/offline mode is derived from the selected `data` source, not from
Expand Down Expand Up @@ -310,7 +312,7 @@ Managed-local fields:

| Field | Default | What to write |
| --- | --- | --- |
| `deployment.disaggregated.managed_local.trainer_cuda_visible_devices` | required | One device token per `nproc_per_node`; trainer and capture devices must not overlap. |
| `deployment.disaggregated.managed_local.trainer_cuda_visible_devices` | required | One device token per trainer rank, or one per independent `windowed_fanout` consumer; trainer and capture devices must not overlap. |
| `deployment.disaggregated.managed_local.mooncake` | default object | Owned loopback Mooncake configuration described by the nested fields below. |
| `deployment.disaggregated.managed_local.capture_servers` | required | One or more owned patched SGLang server definitions. |
| `deployment.disaggregated.managed_local.shutdown_grace_s` | `30` | Positive graceful process-group shutdown window. |
Expand All @@ -336,6 +338,51 @@ endpoints, `store_root`, or `producer_segment_size`. It does not support resume,
an existing torchrun, or `--node-rank`. All owned ports and GPU assignments must
be disjoint.

### Independent windowed fanout

`deployment.disaggregated.windowed_fanout` runs one producer and multiple
single-process consumers from the same YAML. Each child still enters through
`specforge train`; `launch_plan` selects a consumer with `--consumer-id` and
projects its loss, block size, anchors, optimizer schedule, seed, checkpoint,
and output directory onto the canonical trainer configuration.

This topology is intentionally different from data-parallel training. Consumers
advance independently and may have different step costs. A shared SQLite
registry records each cursor and bounded capture interest, while Mooncake owns
the tensor payloads. The producer captures a sample only when a consumer's
window requests it, reuses a live compatible capture across consumers, and
reclaims entries outside every legal window.

Required constraints are:

- online DFlash with Mooncake and exactly one prompt epoch;
- a positive fixed `data.max_prompts`, divisible by batch size times
accumulation;
- `deployment.trainer` fixed at 1x1 because each consumer is its own process;
- exactly one capture server, shared by every consumer;
- one managed-local trainer device per consumer, or one explicit
`cuda_visible_device` on every external consumer;
- `max_live_refs`, `max_live_bytes`, and `max_outstanding_per_consumer` large
enough for the configured batch and capture reservation.

The main bounds and timing controls are:

| Field | Default | Meaning |
| --- | --- | --- |
| `window_lookbehind` / `window_lookahead` | `2` / `40` | Shared default legal window around each consumer cursor. |
| `max_prefetch_per_consumer` | `8` | Maximum speculative requests inside the lookahead window. |
| `max_outstanding_per_consumer` | `8` | Hard per-consumer acquired-ref bound; must cover one accumulated optimizer step. |
| `max_live_refs` / `max_live_bytes` | required byte bound | Global capture capacity shared by all consumers. |
| `capture_reservation_bytes` | 128 MiB | Bytes reserved transactionally before a capture starts. |
| `capture_max_sample_bytes` | 128 MiB | Server-side rejection bound for one captured sample; it cannot exceed the transactional reservation. |
| `capture_batch_size` / `capture_batch_wait_s` | `8` / `0.002` | Producer request batching. |
| `consumer_prefetch_batches` | `1` | Loader-side prefetch workers for each consumer. |

Each consumer may override `window_lookbehind`, `window_lookahead`, and
`max_prefetch` in addition to its required training fields. External deployments
may resume consumers independently with `resume_from`; managed-local runs are
fresh attempts and reject resume checkpoints.

### `runtime`: streaming backpressure

This section affects disaggregated streaming producers and is normally omitted
Expand Down
98 changes: 98 additions & 0 deletions examples/configs/qwen3-8b-dflash-windowed-fanout.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
model:
target_model_path: Qwen/Qwen3-8B
draft_model_config: configs/qwen3-8b-dflash.json
target_backend: sglang
trust_remote_code: true
embedding_key: model.embed_tokens.weight
torch_dtype: bfloat16
mask_token_id: 151669
sglang_attention_backend: flashinfer
sglang_mem_fraction_static: 0.5

data:
train_data_path: ./cache/dataset/perfectblend_qwen3-8b_regen.jsonl
max_prompts: 48
max_length: 3072
chat_template: qwen
build_dataset_num_proc: 32
cache_dir: ./cache

training:
strategy: dflash
num_epochs: 1
max_steps: 24
total_steps: 24
batch_size: 2
accumulation_steps: 1
attention_backend: flex_attention
max_grad_norm: 1.0
save_interval: 0
log_interval: 1
dist_timeout: 30

tracking:
report_to: none

run_id: qwen3-8b-dflash-windowed-fanout
output_dir: ./outputs/qwen3-8b-dflash-windowed-fanout

deployment:
mode: disaggregated
trainer:
nnodes: 1
nproc_per_node: 1
disaggregated:
control_dir: ./outputs/qwen3-8b-dflash-windowed-fanout/control
backend: mooncake
client_buffer_size: 1073741824
windowed_fanout:
window_lookbehind: 2
window_lookahead: 16
max_prefetch_per_consumer: 8
max_outstanding_per_consumer: 8
max_live_refs: 48
max_live_bytes: 25769803776
capture_reservation_bytes: 536870912
capture_max_sample_bytes: 536870912
capture_batch_size: 8
consumer_prefetch_batches: 1
consumers:
- consumer_id: dflash-b4
seed: 42
loss_type: dflash
loss_decay_gamma: 7.0
dpace_alpha: 0.5
draft_block_size: 4
num_anchors: 64
learning_rate: 0.0006
warmup_ratio: 0.04
- consumer_id: dflash-b8
seed: 43
loss_type: dflash
loss_decay_gamma: 7.0
dpace_alpha: 0.5
draft_block_size: 8
num_anchors: 128
learning_rate: 0.0006
warmup_ratio: 0.04
- consumer_id: dflash-b16
seed: 44
loss_type: dflash
loss_decay_gamma: 7.0
dpace_alpha: 0.5
draft_block_size: 16
num_anchors: 256
learning_rate: 0.0006
warmup_ratio: 0.04
managed_local:
trainer_cuda_visible_devices: ["1", "2", "3"]
shutdown_grace_s: 120
mooncake:
protocol: tcp
global_segment_size_bytes: 34359738368
local_buffer_size_bytes: 1073741824
capture_servers:
- port: 30000
cuda_visible_devices: ["0"]
tp_size: 1
mem_fraction_static: 0.5
12 changes: 10 additions & 2 deletions examples/disagg/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,20 @@ trainer in one YAML:
specforge train -c \
examples/configs/qwen3-8b-dflash-1server-dp7-disaggregated.yaml

specforge train -c \
examples/configs/qwen3-8b-dflash-windowed-fanout.yaml

specforge train -c \
examples/configs/qwen3-8b-domino-1server-dp7-disaggregated.yaml
```

These recipes preserve the old DFlash and Domino one-server + DP7
self-contained topologies. The genuine two-server Domino recipe is:
The first recipe preserves the DFlash one-server + DP7 topology. The windowed
recipe instead launches one producer on GPU 0 and three independent DFlash
consumers on GPUs 1-3. They share compatible captures but keep separate cursors,
windows, trainer state, and hyperparameters. Its block/anchor pairs are 4/64,
8/128, and 16/256 so the example does not depend on optional compact-loss or
custom-kernel optimizations. The Domino recipe preserves its
one-server + DP7 topology. The genuine two-server Domino recipe is:

```bash
specforge train -c \
Expand Down
Loading