Repository navigation
Conversation
aoshen02
force-pushed
the
pd-rl/mooncake-transfers
branch
from
October 4, 2026 17:04
c72b167 to
636a6c3
Compare
aoshen02
force-pushed
the
pd-rl/pause-drops-kv
branch
from
October 4, 2026 17:04
20f35c9 to
3efaa1d
Compare
With prefill/decode disaggregation, a pause that clears the cache (wait or keep with clear_cache, sleep at level 1 or above) and release_kv_cache_memory failed with "Failed to reset KV cache": D requests waiting for remote KV, and P's finished requests whose KV D had not pulled yet, still held blocks. A pause that keeps the KV instead waited for those exports, up to VLLM_MOONCAKE_ABORT_REQUEST_TIMEOUT when D was paused too. A pause only stops compute; a cache reset needs every block back. So: - Once the engine is idle, an operation that resets the cache first calls Scheduler.release_transfer_kv() and waits until the transfers give back their blocks, then resets. A resume fails any such operation still pending. - release_transfer_kv() asks the connector to end its transfers (new KVConnectorBase_V1 hook abort_transfers, fanned out by MultiConnector, implemented for Mooncake): P stops holding finished requests' KV for remote readers, and D asks P to drop loads still in flight. A request whose load is cut short is not aborted: it recomputes its KV after resume, through the existing failed-load recovery and whatever the kv_load_failure_policy. - A paused engine does not wait for KV held by remote transfers unless it is releasing it, so a pause that keeps the KV returns at once. - The reset also recomputes waiting requests that hold KV, including remote loads that arrived but were not scheduled, sharing the preemption path. reset_prefix_cache(reset_running_requests=True) returns False while transfers hold blocks, as documented, instead of raising. Signed-off-by: aoshen02 <aoshen@inferact.ai> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aoshen02
force-pushed
the
pd-rl/mooncake-transfers
branch
from
October 5, 2026 02:53
636a6c3 to
3c48419
Compare
aoshen02
force-pushed
the
pd-rl/pause-drops-kv
branch
from
October 5, 2026 02:53
3efaa1d to
0242476
Compare
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.
Purpose
For RL with prefill/decode disaggregation, the trainer pauses P and D, updates the weights, and resumes. With PD, every operation that resets the KV cache failed on D with "Failed to reset KV cache even when all the running requests are preempted…". That covers:
pause(wait|keep, clear_cache=True);sleep(level>=1);release_kv_cache_memory.The reset failed because remote KV transfers still held blocks:
A pause that keeps the KV had the opposite problem: P waited for those exports, up to 480 s when D was paused too and would not pull them.
The fix starts from two facts:
So:
Release, then reset. Once the engine is idle, an operation that resets the cache calls
Scheduler.release_transfer_kv()once. That call:KVConnectorBase_V1.abort_transfers()hook: P stops holding finished requests' KV for remote readers, and D asks P to drop loads still in flight. MultiConnector fans it out; this PR implements it for Mooncake.kv_load_failure_policy. Nothing is aborted (like SGLang's retract, with D recomputing).The engine then waits for the transfers to give their blocks back, and resets. All of this lives in one place,
EngineCoreProc._when_idle. It covers pause withclear_cache, sleep andrelease_kv_cache_memory. A resume fails any such operation still pending.Keep pauses do not wait. A paused engine does not wait for KV that finished requests hold for remote readers, unless it is releasing it. So a pause that keeps the KV returns at once, and the exports finish after resume.
Waiting requests recompute. The reset recomputes waiting requests that hold KV, including remote loads that arrived but were not scheduled yet. It shares the preemption path, and the queue order is kept.
No raise on held blocks.
reset_prefix_cache(reset_running_requests=True)returnsFalsewhile transfers hold blocks, as documented, instead of raising.Docs. The PD note in
async_rl.md: pause both P and D, and usekv_load_failure_policy="recompute".Not covered:
Stacked on vllm-project#59625 and the Mooncake transfer PR (this fork PR's base branch).
Test Plan
Unit: scheduler, async scheduler, engine core, Mooncake, MultiConnector and NIXL suites.
test_release_transfer_kv_frees_blocks_for_resetchecks:test_cache_reset_waits_for_transfer_kvcovers every pause mode andrelease_kv_cache_memory, each idle or draining, with or without held transfers. It drives the real input loop, which must never block on input while work is pending.test_resume_cancels_a_pending_cache_reset.Mutation: each key line removed fails its test (31 of 31 across both PRs).
Hardware: GB300, 1P1D over Mooncake RDMA. The lifecycle matrix covers:
clear_cache;abort_requests;reset_prefix_cache;release_kv_cache_memory;All cases run under load.
Test Result
🤖 Generated with Claude Code