Repository navigation
Conversation
Contributor
|
Documentation preview: https://vllm--59624.org.readthedocs.build/en/59624/ |
aoshen02
force-pushed
the
kv-connector-sleep-registration
branch
from
October 1, 2026 15:56
2050157 to
6b66b1d
Compare
This was referenced Oct 1, 2026
aoshen02
force-pushed
the
kv-connector-sleep-registration
branch
from
October 1, 2026 17:27
6b66b1d to
6d1c3d0
Compare
aoshen02
force-pushed
the
kv-connector-sleep-registration
branch
3 times, most recently
from
October 2, 2026 02:11
853b662 to
4b3a96b
Compare
Contributor
|
This pull request has merge conflicts that must be resolved before it can be |
aoshen02
force-pushed
the
kv-connector-sleep-registration
branch
2 times, most recently
from
October 2, 2026 03:35
5dfcb95 to
c207bcc
Compare
aoshen02
force-pushed
the
kv-connector-sleep-registration
branch
from
October 2, 2026 07:30
c207bcc to
266f652
Compare
…pping Sleep mode unmaps the KV cache and later maps new pages at the same addresses (so does a KV cache discard with the cumem allocator). A KV connector that registered that memory with a transport (RDMA memory regions, IPC handles) keeps transferring through the old pages, which silently corrupts P/D disaggregation. Whether a connector can release such references is a property of its class: `KVConnectorBase_V1.supports_sleep_mode`, False by default, since the base class cannot tell which connectors hold references to the memory; MultiConnector supports it only if every child does. EngineCore refuses a connector without support at startup when sleep mode is enabled; with the cumem allocator alone (which main also supports with such connectors, as long as nothing is unmapped) it refuses a sleep or a KV cache release instead, before anything is unmapped. A registration must live exactly as long as the mapping it covers, so the owner of the mapping signals it: the sleep-mode allocators (CuMem and XPU) run per-tag hooks right before they unmap allocations of a tag (sleep, discard), and after every wake-up that leaves all allocations of the tag mapped. A supporting connector implements `release_kv_caches` (drain, then release what it set up on the memory) and `restore_kv_caches` (set it up again), both idempotent. The worker connector is subscribed for the `kv_cache` tag exactly when it declares support, when it is created, and unsubscribed when it shuts down. A failing release stops that rank's sleep before anything is unmapped; a failing restore is retried by the next wake-up. EngineCore republishes the workers' handshake metadata after a wake-up. A sleep that fails on some rank may have put the others to sleep, so the executor counts as asleep afterwards, as it already does for a failed discard, and a wake-up recovers every rank. For that wake-up to be answered by its own responses, MultiprocExecutor drains every rank's response before raising a rank's failure. Communicator suspension (`enable_nccl_comm_suspend`) is collective, so a rank enters it even when its own allocator step raised. Signed-off-by: aoshen02 <aoshen@inferact.ai> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
aoshen02
force-pushed
the
kv-connector-sleep-registration
branch
from
October 3, 2026 02:19
266f652 to
0c1179b
Compare
Signed-off-by: aoshen02 <aoshen@inferact.ai> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: aoshen02 <aoshen@inferact.ai> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replaces the allocator tag hooks with explicit calls around the KV cache unmap and map, as SGLang does; the base methods default to no-ops. Signed-off-by: aoshen02 <aoshen@inferact.ai> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: aoshen02 <aoshen@inferact.ai> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Author
|
Superseded by #59625, which includes this connector API (with connectors supporting sleep mode by default and only the ones that cannot follow the KV cache remap refused). Closing. |
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.
Problem
Sleep mode (and a KV cache discard with the cumem allocator) unmaps the KV cache, and the wake-up maps new physical pages at the same virtual addresses. A KV connector that registered that memory with a transport (RDMA memory regions in NIXL and Mooncake, IPC handles in others) keeps addressing the old pages. P/D disaggregation then returns wrong output with HTTP 200, and the pinned pages are not freed.
Principle
Design
vllm/device_allocator:register_tag_hooks(tag, before_unmap, after_map)returns the function that unregisters them. CuMem and XPU allocators runbefore_unmapbefore they unmap any allocation of the tag (sleep, discard), so a failing hook leaves everything mapped, andafter_mapafter every wake-up that leaves all allocations of the tag mapped. Restores are idempotent, so the next wake-up retries a failed one.KVConnectorBase_V1.supports_sleep_modeis False by default;MultiConnectorsupports it only if every child does and forwards to them. A supporting connector implementsrelease_kv_caches(drain, then release) andrestore_kv_caches.ensure_kv_transfer_initializedsubscribes the worker connector for thekv_cachetag exactly when it declares support;ensure_kv_transfer_shutdownunsubscribes it. Declaring support therefore means being called.EngineCorerefuses an unsupported connector at startup when sleep mode is enabled. With the cumem allocator alone (supported on main with any connector as long as nothing is unmapped),sleep(level >= 1)andrelease_kv_cache_memory()refuse it before anything is unmapped. After a wake-up it republishes the workers' handshake metadata, since the KV cache was registered anew.Executor.sleepcounts as asleep even if a rank failed (asdiscardalready does);MultiprocExecutor.collective_rpcdrains every rank's response before raising, so the next RPC is answered by its own responses;enable_nccl_comm_suspend) even when its own allocator step raised.NIXL support: #59635 (on this PR and #59713). Mooncake over RDMA: #59625.
Behaviour change
With sleep mode enabled, an engine whose KV connector does not declare support fails at startup with
<Connector> does not support sleep mode; with the cumem allocator alone, the sleep or KV cache release fails instead. A connector opts in by declaring support and implementing release and restore. One that only copies KV blocks (offload connectors) releases by waiting for its queued and in-flight copies and restores nothing; none is switched on here before its own hardware validation.Tests
Mutation check: 22 mutations, all killed (each hook call, the mapped/asleep filters, subscription, unsubscription, MultiConnector all/forwarding, each refusal, the republish, the executor
finally, the RPC drain, both commfinallys).test_cumem.py::test_tag_hooks_bracket_the_mapping_of_their_tag(real allocator): hooks bracket sleep, discard and selective wake for every subscriber; a failed restore is retried by a wake-up that maps nothing; a failingbefore_unmapleaves everything mapped.test_kv_connector_lifecycle.py: through the realensure_kv_transfer_initialized/shutdown, a supporting connector is released and restored around the mapping, an unsupported one never is, and a shut down one is not called.test_engine_core.py: startup refusal on a real engine; refusal before unmapping for sleep levels 1 and 2 and the KV cache release, never for a pause; republish after wake-up.test_executor.py,test_multiproc_executor.py,test_sleep_mode_backend.py(comm suspension, also when the backend step raises),test_multi_connector.py.Not covered
AI assistance: written with Claude Code and reviewed by the submitter.
🤖 Generated with Claude Code