Skip to content

[DCP] [HiCache] Support role-local DCP storage in prefill/decode serving (upstream #41695) - #19

Merged
Venkat2811 merged 5 commits into
kimi-k3-v0.5.22from
venkat/v0522-5-pd-dcp
Oct 19, 2026
Merged

Venkat2811 merged 5 commits into
kimi-k3-v0.5.22from
venkat/v0522-5-pd-dcp

Conversation

@Venkat2811

@Venkat2811 Venkat2811 commented Oct 19, 2026 •

Copy link
Copy Markdown
Collaborator

Layer 6, the head of the kimi-k3-v0.5.22 stack. Mirror of sgl-project#41695: its five commits (9994a5f322 .. ed850058f8, the 16 Oct PR head) cherry-picked onto layer 5 without conflict.

Role-local DCP storage in prefill/decode serving: a decode with its own L3 keeps its cache promises and the live recurrent state it already received, tracks pending restores through the current cache locks, and validates a runtime attach with the effective prefetch policy. v0.5.22 already has the decode Mamba pre-allocation check (sgl-project#41927); the rest is still needed for DCP L3 inside P/D (long-ctx recipe with a TP16 prefill; any future decode L3). Neither live copy uses it today; it is carried so one release serves every recipe.

Upstream: sgl-project#41695

Check (19 Oct 2026, HGX B300, lmsysorg/sglang:v0.5.22-cu130) Result
Stack CPU selection (CUDA hidden) 29 / 29 pass
Native Mooncake round trip over TCP plain, --controller, --hybrid: all PASS
test_hybrid_l3_restore.py (1 GPU, both tree cores, cancellation, live state) 4 / 4 pass
sgl-project#41695's P/D harness: Kimi-Linear prefill TP4/DCP1 to decode TP4/DCP4 on one node, RDMA, mini load balancer, file L3 with lifecycle PASS on the Python and the Rust tree core: 22 requests each; fresh roles restored 192 / 448 / 960 tokens from L3 (logprob delta 0.0); 3 concurrent follows; abort then retry; I/O failure then retry (max delta 0.013 against 0.2)
Same harness, Mooncake L3 attached at runtime over HTTP PASS: 16 requests, 192 / 448 / 960 tokens from MooncakeStore, missing-state fallback

Kimi-K3 on this head (full model, one HGX B300 node per role, the v0.5.22 image with this head checked out in place, Rust tree core):

Check Result
Aggregated worker, the llmaas kimi-k3-agg-b300 shape (TP8 x DCP8, host tier 160 GB per rank, Mooncake L3, Triton KDA) starts on all 8 ranks (host pools 112.85 GB KV + 47.16 GB state each, no refusal; v0.5.22 alone refuses this recipe); GSM8K 31/32, 0 errors; chat and tool calls 20/20; L3 restore gates short (4 x 7K) and long (4 x 21K): every reader restored from MooncakeStore with nothing from GPU or host (6,656 and 20,480 tokens each; 26,624 and 82,432 in total, the same as the 3 Oct v0.5.21 line); multi-sequence prefill 0 broken of 66
Same worker, AgentX 32 lanes for 20 min 0 errors, engine up throughout, 0 broken answers after; one node at the four-node copy's line, so the answer-speed rule breaks (p50 23.5 tok/s), as expected
Prefill/decode, 1 + 1 (prefill TP8/DCP1/EP8 + host tier + Mooncake L3, decode TP8 x DCP8) GSM8K 31/32, 0 errors; chat and tool calls 20/20; L3 restore gates short and long pass; multi-sequence 0 broken

Two things seen on the way, neither from this stack: v0.5.22 does not refresh sglang:hicache_host_used_tokens while the engine is idle (it reads stale after /flush_cache until the next batch), and on the P/D prefill the first L3 lookup after /flush_cache usually finds nothing (5 of 6 runs with layer 1 alone, 7 of 7 on this head; later lookups restore).

🤖 Generated with Claude Code


CI States

Latest PR Test (Base): 🚫 Run #39311072013
Latest PR Test (Extra): 🚫 Run #39311071568
Latest PR Test (AMD ROCm 10): 🚫 Run #39311071477

…nt state

Reuse upstream Mamba admission with reserved checkpoint slots, decline unregistered prefetch hits before advertising them, and keep incoming recurrent state separate from cache restoration. Require wait-complete prefetch and reject unqualified decode offload for DCP L3.

(cherry picked from commit 9994a5f)
Use upstream restore locks for pending capacity and GPU assertions. Drop the obsolete pre-gate failure test already covered by upstream gated receiver tests.

(cherry picked from commit 7f48a80)
Pass the selected policy through both controller layers instead of rechecking the startup default. Exercise real controller validation in the attach regression; timeout-to-wait_complete and retained-policy reattach fail before this change.

(cherry picked from commit ed85005)
@Venkat2811
Venkat2811 force-pushed the venkat/v0522-5-pd-dcp branch from b43300f to 3e932ec Compare October 19, 2026 19:26
@Venkat2811
Venkat2811 changed the base branch from venkat/v0522-4-hybrid-dcp to kimi-k3-v0.5.22 October 19, 2026 19:26
@Venkat2811
Venkat2811 merged commit aadcdcf into kimi-k3-v0.5.22 Oct 19, 2026
2 of 5 checks passed
Venkat2811 added a commit that referenced this pull request Oct 27, 2026
…e slots (upstream sgl-project#41695)

Layer 12 of the Kimi-K3 nightly line on upstream main 5884e4f.

The prefill/decode part of upstream sgl-project#41695 that 5884e4f does not have. A
decode server with --disaggregation-decode-enable-radix-cache and HiCache
restores the cached prefix locally while prefill sends the rest:

- The transfer-side load-back handed the request to init_load_back, so for a
  hybrid (Mamba/KDA) model it also copied the host checkpoint at the prefix
  end into the request's own state slot. That slot receives the live state
  prefill computes for the whole prompt; whichever copy lands last wins.
  InitLoadBackParams.restore_request_state=False restores the canonical
  cache slot only.
- A hybrid restore needs one canonical state slot besides the request's live
  slot. Admission keeps a slot free for each queued restore
  (ensure_mamba_capacity(..., reserved_slots=)) and promises prefill only
  the device-resident prefix when no slot can be reclaimed; before, the
  promise went out and the restore failed after prefill had skipped those
  tokens.
- Under DCP, a decode server with an L3 backend requires
  --hicache-storage-prefetch-policy wait_complete (decode promises the probed
  L3 span before the read completes) and refuses
  --disaggregation-decode-enable-offload-kvcache, as sgl-project#41695 did. Checked at
  startup (resolve_hicache_dcp_compatibility) and on runtime attach,
  including the same-backend policy update (StorageAttachment.attach;
  HiCacheController.attach_storage_backend never sees the effective policy).

Source: 91ecb13 on the kimi-k3-nightly-3c560089 line, which equals
upstream sgl-project#41695's own commits over sgl-project#41694 (head ed85005). Dropped because
5884e4f has it: starting the L3 prefetch before preallocation and
promising only the span it took (sgl-project#43548). The sgl-project#41693/sgl-project#41694 ports that
91ecb13 sat on are superseded by sgl-project#41187 (no P/D refusal, no
decode-offload case), so the guards are re-expressed on upstream's structure
and the tests are rewritten on 5884e4f's fixtures. No change for a decode
server without the decode radix cache, which is every K3 recipe today.

Tests (CPU), this commit's test files on the parent: test_server_args.py
TestHiCacheArgs::test_dcp_decode_storage_requires_wait_complete_without_offload
3 subtests fail (NotImplementedError not raised for timeout, best_effort and
decode offload); test_hicache_dcp_host_pool.py TestDcpDecodeStorageAttach 6
subtests fail (attach accepted an early-stopping policy, attached or not);
test_mamba_capacity.py test_pd_restore_promise_keeps_a_canonical_state_slot
2 subtests fail (full and pending_restore promised 6 tokens, not 2). With
this commit all pass.
Tests (GPU, one B300): test_unified_radix_cache_load_back.py
Test_FULL_MAMBA_ps1::test_pd_decode_restore_keeps_the_live_request_state
fails on the parent (the live slot ends with the checkpoint's marker 11,
not the live 37) and passes with this commit.

Fork PR (v0.5.22 line): #19
Upstream: sgl-project#41695

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Venkat2811 added a commit that referenced this pull request Oct 27, 2026
…e slots (upstream sgl-project#41695)

Layer 12 of the Kimi-K3 nightly line on upstream main 5884e4f.

The prefill/decode part of upstream sgl-project#41695 that 5884e4f does not have. A
decode server with --disaggregation-decode-enable-radix-cache and HiCache
restores the cached prefix locally while prefill sends the rest:

- The transfer-side load-back handed the request to init_load_back, so for a
  hybrid (Mamba/KDA) model it also copied the host checkpoint at the prefix
  end into the request's own state slot. That slot receives the live state
  prefill computes for the whole prompt; whichever copy lands last wins.
  InitLoadBackParams.restore_request_state=False restores the canonical
  cache slot only.
- A hybrid restore needs one canonical state slot besides the request's live
  slot. Admission keeps a slot free for each queued restore
  (ensure_mamba_capacity(..., reserved_slots=)) and promises prefill only
  the device-resident prefix when no slot can be reclaimed; before, the
  promise went out and the restore failed after prefill had skipped those
  tokens.
- Under DCP, a decode server with an L3 backend requires
  --hicache-storage-prefetch-policy wait_complete (decode promises the probed
  L3 span before the read completes) and refuses
  --disaggregation-decode-enable-offload-kvcache, as sgl-project#41695 did. Checked at
  startup (resolve_hicache_dcp_compatibility) and on runtime attach,
  including the same-backend policy update (StorageAttachment.attach;
  HiCacheController.attach_storage_backend never sees the effective policy).

Source: 91ecb13 on the kimi-k3-nightly-3c560089 line, which equals
upstream sgl-project#41695's own commits over sgl-project#41694 (head ed85005). Dropped because
5884e4f has it: starting the L3 prefetch before preallocation and
promising only the span it took (sgl-project#43548). The sgl-project#41693/sgl-project#41694 ports that
91ecb13 sat on are superseded by sgl-project#41187 (no P/D refusal, no
decode-offload case), so the guards are re-expressed on upstream's structure
and the tests are rewritten on 5884e4f's fixtures. No change for a decode
server without the decode radix cache, which is every K3 recipe today.

Tests (CPU), this commit's test files on the parent: test_server_args.py
TestHiCacheArgs::test_dcp_decode_storage_requires_wait_complete_without_offload
3 subtests fail (NotImplementedError not raised for timeout, best_effort and
decode offload); test_hicache_dcp_host_pool.py TestDcpDecodeStorageAttach 6
subtests fail (attach accepted an early-stopping policy, attached or not);
test_mamba_capacity.py test_pd_restore_promise_keeps_a_canonical_state_slot
2 subtests fail (full and pending_restore promised 6 tokens, not 2). With
this commit all pass.
Tests (GPU, one B300): test_unified_radix_cache_load_back.py
Test_FULL_MAMBA_ps1::test_pd_decode_restore_keeps_the_live_request_state
fails on the parent (the live slot ends with the checkpoint's marker 11,
not the live 37) and passes with this commit.

Fork PR (v0.5.22 line): #19
Upstream: sgl-project#41695

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation hicache unified-radix-cache

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant