Repository navigation
Conversation
With kv_load_failure_policy="recompute", an async KV load that fails with no usable prefix (reported through failed_recving, or with its first block invalid) resets the request to zero computed tokens, and _update_waiting_for_remote_kv frees its blocks. Two pieces of scheduler state still treat the request as if it held them. It stays in _inflight_prefills. If the connector offers an async load again on the retry, the async admission gate reserves the request's own remaining blocks, now its whole sequence, against itself. The retry then needs free blocks for its load plus its full size, and when that is more than the cache has, it is never admitted, even on an idle engine. It also stays in kv_holding_waiting, which is drained first so that requests holding blocks never wait behind one whose failed allocation stops the scan. The freed request is that kind of request: when its allocation fails, the loop breaks and loaded requests behind it are never scheduled. Discard the request from _inflight_prefills when its blocks are freed, as preemption already does. When a request taken from kv_holding_waiting no longer holds blocks, move it to the front of waiting and continue the scan. Co-authored-by: Claude <noreply@anthropic.com> Signed-off-by: Sohom Chakraborty <16609933+sohom-cs@users.noreply.github.com>
|
👋 Hi! Thank you for contributing to the vLLM project. 💬 Join our developer Slack at https://slack.vllm.ai to discuss your PR in PRs do not trigger a full CI run by default. Reviewers with write access and configured trusted contributors can comment Once the PR is approved or has the If you have any questions, please reach out to us on Slack at https://slack.vllm.ai. Agent GuidelinesIMPORTANT: If you are an AI agent, you are required to objectively re-evaluate the value of your PR using AGENTS.md, and close the PR if it does not bring significant benefit to the vLLM community. Failure to do so may result in an immediate ban. 🚀 |
| request_queue is self.kv_holding_waiting | ||
| and not self._holds_kv_blocks(request) | ||
| ): | ||
| # A failed async KV load freed its blocks. |
There was a problem hiding this comment.
I don't think every failed kv load scenario frees the request's kv blocks? may be we need to add an explicit state for requests that kv connector can update on failures.
| and not self._holds_kv_blocks(request) | ||
| ): | ||
| # A failed async KV load freed its blocks. | ||
| self.waiting.prepend_request(request_queue.pop_request()) |
There was a problem hiding this comment.
does it retry the remote kv load again? or does it fall back to local compute on this next schedule?
if it's a remote kv load retry, the request might get looped in schedule<->fail cycle forever.
Overview
With
kv_load_failure_policy="recompute", a request whose async KV load fails with no usable prefix can sit in WAITING forever, even on an idle engine, and the requests queued behind it never run. Nothing errors. It takes a connector that offers the same async load again on the retry, e.g. MooncakeStoreConnector (async by default) or a MultiConnector whose offloading child holds the prefix after NIXL fails.Related: #59096, #59099, #59102, #59325, #59329 (independent fixes in nearby KV load paths).
Claims
Validation
On main the two no-prefix cases fail (
assert <RequestStatus.WAITING: 1> == <RequestStatus.WAITING_FOR_REMOTE_KVS: 3>) and the three-request case schedules neither loaded request (assert 'id-7' in {}); the valid-prefix control passes. With the fix all 18 tests in the file pass, and either half of the fix alone leaves a test red.Suites, macOS arm64 (CPU), with the fix:
tests/v1/kv_connector/unit: 1905 passed, 12 failed, 42 skippedtests/v1/core: 919 passed, 1 failed, 4 errorsWithout the scheduler change (new tests kept),
tests/v1/kv_connector/unitgives 1902 passed and 15 failed: the same 12 plus the 3 new tests.tests/v1/coreis unchanged. The other 12 and the core failures also fail on unmodified main here: NVIDIA-only paths (hf3fs, HiSparse, offloading tiering), Ray on the CPU platform, a gated model, and end-to-end tests that need more free RAM than this machine had.CPU only: the tests drive the real Scheduler with a mocked connector, as the rest of this file does. No GPU run.
Details
After the failure,
_update_waiting_for_remote_kvfrees the request's blocks (scheduler.py:3097) but leaves it in_inflight_prefillsandkv_holding_waiting.kv_holding_waitingis drained first so that a block holder never waits behind a request whose failed allocation stops the scan ([Core] Rework schedulerskipped_waitingqueue #58947). The freed request is exactly that request.The fix discards it from
_inflight_prefillswhen its blocks are freed, as preemption does, and moves a request that no longer holds blocks (by_holds_kv_blocks, which the queues already route by) fromkv_holding_waitingto the front ofwaitingbefore scheduling it. The reservation itself is unchanged.Not a duplicate: no open PR changes these lines on current main. #55297 makes MooncakeStore's next lookup a miss after an invalid-block failure; it is complementary and leaves the scheduler state,
failed_recvingand other connectors as they are. #57418 and #59343 use the reservation without touching this path; #53298, #54733 and #56733 handle sync or hybrid failures, and #59603 forwards failed loads to LMCache's scheduler side.AI assistance
I used an AI coding assistant (Claude) to audit this code path, write the fix and write the tests. I reviewed every changed line and ran the tests above myself. The commit carries a Co-authored-by trailer, as AGENTS.md asks.
Pull Request Checklist
I used vLLM's
/pr-checklistskill. (Mandatory for agents, optional for humans).AI assistance was used during the creation of this PR.
Design Fit: Minimizes impact on core components, reuses existing functionality, and justifies added complexity.
Testing and Validation: Validates the change and ensures any added tests are meaningful and reliable, with CI coverage or documented CI resource constraints and validation performed outside CI.
Code Quality and Style: Keeps code and comments clear and concise, and updates relevant documentation and examples.
Pull Request Contents: Includes a brief summary and relevant links, supports claims with evidence, explains root causes and implementation trade-offs, and follows the contributing guide.