Skip to content

[PD] Transfer the DCP-replicated DSPARK draft KV in DCP1->DCP-N relayouts - #37709

Merged
kpham-sgl merged 10 commits into
sgl-project:mainfrom
kpham-sgl:pd-dcp-dspark-replicated-draft-kv
Sep 12, 2026
Merged

kpham-sgl merged 10 commits into
sgl-project:mainfrom
kpham-sgl:pd-dcp-dspark-replicated-draft-kv

Conversation

@kpham-sgl

@kpham-sgl kpham-sgl commented Sep 3, 2026 •

Copy link
Copy Markdown
Collaborator

Follow-up to #35762: ship DSpark draft KV from a DCP1 prefill to a DCP-N decode.

Design

Decode publishes one virtual page list. A virtual page is P*N tokens (P = physical page, N = decode DCP size). Each pool then lays that page out at its own width:

page = dst_pages[pos // (P*N)]
off  = pos % (P*N)                 # offset inside that virtual page

draft  row = page * (P*N) + off    # page is wide; keep every token
target row = page * P + off // N   # page is narrow; keep every Nth token (owner pos % N)

Target: strided pick + #35762 pack. Draft: full copy, no pack.

Code

  • KVArgs.num_draft_entries marks the draft tail of kv_data_ptrs.
  • build_dcp_token_transfer_plan fills both index maps in one call.
  • prepare_dcp_token_item_lens scales draft dest pages by N. Pack buffers stay target-only.
  • Mooncake and NIXL send both parts from that plan (NIXL: two xfers, existing _part_{i}_{n} notif).

Out of scope: DCP>1 prefill, heterogeneous P/D TP × DSPARK.

Tests

  • test_dcp_pack.py: golden rows, chunk crossing, pack vs no-pack grouping, item-len scale.
  • test_kimi_linear_pd_dcp4_dspark.py: Kimi-Linear TP4 DCP1 → DCP4 DSPARK, GSM8K.

Speed Tests

8xB300, Kimi-Linear-48B-A3B-Instruct, dummy DSPARK + SGLANG_SIMULATE_ACC_LEN=4 (measured accept length 4.00). Same topology as #35762. OSL 32. ISL 128k/256k measured with SSE-framed TTFT (MiniLB can coalesce events; sglang.benchmark.serving treating each HTTP chunk as one JSON reported Mooncake 128k TTFT=0).

NIXL

ISL conc TTFT p50 out tok/s
4096 1 123.4 178.8
4096 8 292.8 530.6
32768 1 437.4 65.2
32768 8 3087.9 77.2
131072 1 1543 20.2
131072 8 12015 20.9
262144 1 3508 9.0
262144 8 27685 9.2

Mooncake (TCP)

ISL conc TTFT p50 out tok/s
4096 1 122.2 194.2
4096 8 841.4 241.3
32768 1 391.4 73.0
32768 8 2945.8 81.2
131072 1 1527 20.4
131072 8 11936 21.1
262144 1 3485 9.0
262144 8 27175 9.3

CI States

Latest PR Test (Base): 🚫 Run #34654691933
Latest PR Test (Extra): ⏳ Run #34661035645
Latest PR Test (AMD ROCm 10): ❌ Run #34654691978

kpham-sgl and others added 2 commits September 2, 2026 21:14
…outs

The DCP1->DCP-N relayout (sgl-project#35762) covered only the owner-strided target MLA
rows; DSPARK was left to a follow-up. The decode's draft pool is replicated
across DCP ranks and indexes the shared allocator's widened virtual locs raw,
so its rows need a second, non-strided plan: every chunk token to every rank,
addressed at dst_pages[pos // (P*N)] * (P*N) + pos % (P*N) from the same page
list the target plan collapses by dcp_size.

- KVArgs.num_draft_entries marks the draft tail of kv_data_ptrs on both peers.
- build_dcp_replicated_token_transfer_plan emits the widened-loc plan; the
  draft rows are page-contiguous on the prefill so they need no pack gather.
- prepare_dcp_token_item_lens validates the draft tail at the widened page
  scale (page_size * dst_dcp_size) instead of rejecting it as a geometry
  mismatch; pack buffers size from target entries only.
- mooncake sends both parts in one synchronous call; NIXL splits them into
  _part_{i}_{n} transfers reassembled by the existing chunk-part tracking.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@kpham-sgl

kpham-sgl commented Sep 3, 2026 •

Copy link
Copy Markdown
Collaborator Author

Ran HEAD (0b4a285) on 8×B300 with test/registered/disaggregation/test_kimi_linear_pd_dcp4_dspark.py (dummy DSPARK draft). N=10 GSM8K (400) + spec_verify after a single server launch per backend. Threshold 0.88. All 20 runs passed; spec_verify_ct=31 every run.

Mooncake (default; IB uverbs not accessible in the pod → TCP fallback)

run 1 2 3 4 5 6 7 8 9 10
score 0.9225 0.925 0.9175 0.925 0.915 0.9175 0.925 0.925 0.9225 0.920

mean 0.9215, std 0.0038, min 0.915, max 0.925

NIXL (UCX)

run 1 2 3 4 5 6 7 8 9 10
score 0.920 0.930 0.935 0.935 0.9275 0.9325 0.935 0.9325 0.9225 0.925

mean 0.9295, std 0.0055, min 0.920, max 0.935

Accept length: 1.00 on every run / decode-log sample (accept rate: 0.00). Dummy draft never accepts a draft token, so this is only the bonus token — not a real acc-len distribution.

@kpham-sgl
kpham-sgl force-pushed the pd-dcp-dspark-replicated-draft-kv branch 2 times, most recently from 972e2fd to 0b4a285 Compare September 3, 2026 23:29
Drop the replicated-plan helper and dest-page validators. One call fills
both index maps so mooncake/nixl do not plan twice.

Co-authored-by: Cursor <cursoragent@cursor.com>
@kpham-sgl

Copy link
Copy Markdown
Collaborator Author

Ran HEAD (7b0c679) on 8×B300 with test/registered/disaggregation/test_kimi_linear_pd_dcp4_dspark.py (dummy DSPARK draft). One full pass per backend after a server launch. Threshold 0.88. Both passed; spec_verify ok.

backend GSM8K acc len
Mooncake (TCP fallback; IB uverbs not accessible) 0.910 1.00
NIXL (UCX) 0.905 1.00

Accept length is the dummy-draft bonus token only (accept rate: 0.00).

Replace formula-echo checks with small P/N cases so a swapped dest page
size or a rank-ownership bug fails.

Co-authored-by: Cursor <cursoragent@cursor.com>
@kpham-sgl
kpham-sgl marked this pull request as ready for review September 4, 2026 01:31
@kpham-sgl

Copy link
Copy Markdown
Collaborator Author

/rerun-test test/registered/disaggregation/test_kimi_linear_pd_dcp4_dspark.py test/registered/disaggregation/test_kimi_linear_pd_dcp4.py

@github-actions

github-actions Bot commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

Results for /rerun-test test/registered/disaggregation/test_kimi_linear_pd_dcp4_dspark.py test/registered/disaggregation/test_kimi_linear_pd_dcp4.py:

🚀 8-gpu-b200 (2 tests): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_kimi_linear_pd_dcp4_dspark.py
cd test/ && python3 registered/disaggregation/test_kimi_linear_pd_dcp4.py

@kpham-sgl

Copy link
Copy Markdown
Collaborator Author

/rerun-test test/registered/disaggregation/test_kimi_linear_pd_dcp4_dspark.py test/registered/disaggregation/test_kimi_linear_pd_dcp4.py

@github-actions

github-actions Bot commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

Results for /rerun-test test/registered/disaggregation/test_kimi_linear_pd_dcp4_dspark.py test/registered/disaggregation/test_kimi_linear_pd_dcp4.py:

🚀 8-gpu-b200 (2 tests): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_kimi_linear_pd_dcp4_dspark.py
cd test/ && python3 registered/disaggregation/test_kimi_linear_pd_dcp4.py

@kpham-sgl

Copy link
Copy Markdown
Collaborator Author

/rerun-group disaggregation

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

⚠️ Rebase Required Before Re-run

A major update has landed on main. Your PR is diverged relative to required base commit a5f07b1241fc.

Re-run was not dispatched. What to do:

  • Rebase your branch onto the latest main and push again
  • Follow issue #21065 for context
  • CI-fix PRs may request the bypass-maintenance label to skip this check

@kpham-sgl

Copy link
Copy Markdown
Collaborator Author

/rerun-group disaggregation

@github-actions

github-actions Bot commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

Results for /rerun-group disaggregation:

🚀 4-gpu-gb300 (1 test): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_disaggregation_aarch64.py

🚀 2-gpu-h100 (5 tests): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_disaggregation_basic.py
cd test/ && python3 registered/disaggregation/test_disaggregation_decode_offload.py
cd test/ && python3 registered/disaggregation/test_disaggregation_optimistic_prefill.py
cd test/ && python3 registered/disaggregation/test_disaggregation_rust_server.py
cd test/ && python3 registered/disaggregation/test_disaggregation_unified_memory.py

🚀 8-gpu-h20 (5 tests): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_disaggregation_decode_radix_cache.py
cd test/ && python3 registered/disaggregation/test_disaggregation_different_tp.py
cd test/ && python3 registered/disaggregation/test_disaggregation_dp_attention.py
cd test/ && python3 registered/disaggregation/test_disaggregation_nixl.py
cd test/ && python3 registered/disaggregation/test_disaggregation_pp.py

🚀 8-gpu-h200 (4 tests): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_disaggregation_decode_radix_cache_swa.py
cd test/ && python3 registered/disaggregation/test_disaggregation_dsv4.py
cd test/ && python3 registered/disaggregation/test_disaggregation_hisparse.py
cd test/ && python3 registered/disaggregation/test_disaggregation_hybrid_attention.py

🚀 4-gpu-b200 (2 tests): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_disaggregation_dwdp_gpt_oss.py
cd test/ && python3 registered/disaggregation/test_disaggregation_inkling_mxfp8.py

🚀 4-gpu-h100 (2 tests): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_disaggregation_kimi_linear.py
cd test/ && python3 registered/disaggregation/test_epd_disaggregation.py

🚀 1-gpu-5090 (1 test): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_disaggregation_xpu.py

🚀 8-gpu-b200 (2 tests): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_kimi_linear_pd_dcp4.py
cd test/ && python3 registered/disaggregation/test_kimi_linear_pd_dcp4_dspark.py

whybeyoung added a commit that referenced this pull request Sep 4, 2026
…outs

Cherry-pick of #37709 (net diff).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
kpham-sgl and others added 3 commits September 9, 2026 14:17
…red/e2e/

main now requires new registered tests to live under
test/registered/<kind>/<subsystem>/ (scripts/lint/check_registered_tests.py).
The test launches a PD pair and checks GSM8K plus that spec-verify runs on the
decode side, so it is an e2e test.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…virtual page

test_second_chunk_crosses_dest_pages placed the chunk at send-range pos 4..7,
which is exactly one virtual page (P*N=4), yet its draft golden mixed rows from
virtual pages 4 and 6. Start the chunk at src_page_offset=1 (pos 2..5) so it
really crosses the page boundary, and pin both target and draft goldens to the
row mapping the plan builder (and main's target path) implement.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Comment on lines +98 to +99
"--speculative-draft-load-format",
"dummy",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this CI test detect a wrong draft mapping?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this test is not really strong. We will train a separate drafter for Kimi Linear and use it in CI in the future

@ShangmingCai ShangmingCai left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good. Verified and tested. No other comment.

@kpham-sgl kpham-sgl added the run-ci CI: run the baseline test suite on this PR label Sep 11, 2026
@kpham-sgl

Copy link
Copy Markdown
Collaborator Author

/rerun-group disaggregation

@kpham-sgl

Copy link
Copy Markdown
Collaborator Author

/rerun-test test/registered/disaggregation/test_kimi_linear_pd_dcp4_dspark.py test/registered/disaggregation/test_kimi_linear_pd_dcp4.py

@github-actions

github-actions Bot commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Results for /rerun-group disaggregation:

🚀 4-gpu-gb300 (1 test): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_disaggregation_aarch64.py

🚀 2-gpu-h100 (6 tests): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_disaggregation_basic.py
cd test/ && python3 registered/disaggregation/test_disaggregation_chunked_prefill_abort.py
cd test/ && python3 registered/disaggregation/test_disaggregation_decode_offload.py
cd test/ && python3 registered/disaggregation/test_disaggregation_optimistic_prefill.py
cd test/ && python3 registered/disaggregation/test_disaggregation_rust_server.py
cd test/ && python3 registered/disaggregation/test_disaggregation_unified_memory.py

🚀 8-gpu-h20 (5 tests): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_disaggregation_decode_radix_cache.py
cd test/ && python3 registered/disaggregation/test_disaggregation_different_tp.py
cd test/ && python3 registered/disaggregation/test_disaggregation_dp_attention.py
cd test/ && python3 registered/disaggregation/test_disaggregation_nixl.py
cd test/ && python3 registered/disaggregation/test_disaggregation_pp.py

🚀 8-gpu-h200 (4 tests): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_disaggregation_decode_radix_cache_swa.py
cd test/ && python3 registered/disaggregation/test_disaggregation_dsv4.py
cd test/ && python3 registered/disaggregation/test_disaggregation_hisparse.py
cd test/ && python3 registered/disaggregation/test_disaggregation_hybrid_attention.py

🚀 4-gpu-b200 (2 tests): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_disaggregation_dwdp_gpt_oss.py
cd test/ && python3 registered/disaggregation/test_disaggregation_inkling_mxfp8.py

🚀 4-gpu-h100 (2 tests): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_disaggregation_kimi_linear.py
cd test/ && python3 registered/disaggregation/test_epd_disaggregation.py

🚀 1-gpu-5090 (1 test): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_disaggregation_xpu.py

🚀 8-gpu-b200 (1 test): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_kimi_linear_pd_dcp4.py

@github-actions

github-actions Bot commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Results for /rerun-test test/registered/disaggregation/test_kimi_linear_pd_dcp4_dspark.py test/registered/disaggregation/test_kimi_linear_pd_dcp4.py:

🚀 8-gpu-b200 (1 test): ✅ View workflow run

cd test/ && python3 registered/disaggregation/test_kimi_linear_pd_dcp4.py

⛔ test/registered/disaggregation/test_kimi_linear_pd_dcp4_dspark.py: File not found: test/registered/disaggregation/test_kimi_linear_pd_dcp4_dspark.py

@kpham-sgl

Copy link
Copy Markdown
Collaborator Author

/rerun-test test/registered/e2e/disaggregation/test_kimi_linear_pd_dcp4_dspark.py

@github-actions

github-actions Bot commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Results for /rerun-test test/registered/e2e/disaggregation/test_kimi_linear_pd_dcp4_dspark.py:

🚀 8-gpu-b200 (1 test): ✅ View workflow run

cd test/ && python3 registered/e2e/disaggregation/test_kimi_linear_pd_dcp4_dspark.py

…ontract

`send_kvcache_dcp` now returns one handle per transfer part (target + draft),
and the worker extends its handle list with the result. The test merged from
main (sgl-project#35762) still mocked a single string handle, so `extend` split it into
characters and the chunk barrier polled 41 fake handles instead of 3. The fake
`kv_args` also lacked `num_draft_entries`, which the pack path now reads.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@kpham-sgl
kpham-sgl merged commit a207786 into sgl-project:main Sep 12, 2026
127 of 145 checks passed
@kpham-sgl kpham-sgl added the release-highlight Candidate PR for release note highlight label Sep 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

jit-kernel release-highlight Candidate PR for release note highlight run-ci CI: run the baseline test suite on this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants