Skip to content

[Bugfix][HiSparse] Account for GPU copies during prefix admission - #57457

Closed
S1ro1 wants to merge 1 commit into
vllm-project:mainfrom
S1ro1:fix/hisparse-copy-admission
Closed

S1ro1 wants to merge 1 commit into
vllm-project:mainfrom
S1ro1:fix/hisparse-copy-admission

Conversation

@S1ro1

@S1ro1 S1ro1 commented Sep 18, 2026

Copy link
Copy Markdown
Contributor

A HiSparse host-prefix cache hit can re-pin free GPU shadow copies before allocating the request's hot region. Those pins were omitted from device-block admission, so a request could pass the capacity check and then crash the engine with Cannot get 64 free blocks from the pool.

This change counts the unique, currently free GPU copies associated with the local host-prefix hit. The host manager includes that cost in the existing admission calculation; running requests and already-pinned copies add no cost. Under pressure, admission returns None so the scheduler can defer the request instead of exhausting the pool. GPU-copy reuse is preserved.

The regression uses real CPU block pools through KVCacheManager.allocate_slots. It exercises three insufficient-capacity cases, an exact-fit case, retry after pressure is released, and preservation of surviving copies when one earlier copy was evicted.

Validation

Base: upstream 213c379.

  • Unmodified production code: the new pressure regression reproduced three allocator exceptions; the exact-fit case passed.
  • Final prefix-cache suite: 163 passed, no deselected tests, on 8def699 (format-only changes after the test run).
  • All applicable pre-commit hooks passed, including ruff, formatting, and mypy.
PYTHONPATH="$PWD" VLLM_PLUGINS='' uv run --project "$TEST_ENV" --no-sync python "$CPU_TEST_WRAPPER" \
  --confcutdir=tests/v1/core tests/v1/core/test_prefix_caching.py \
  -k 'not test_fewer_blocks_with_hma' -q
uv tool run --from 'pre-commit>=4.5.1' pre-commit run --files \
  vllm/v1/core/single_type_kv_cache_manager.py \
  vllm/v1/hisparse/coordinator.py tests/v1/core/test_prefix_caching.py

TEST_ENV is the prepared vLLM/Prime RL dependency environment. CPU_TEST_WRAPPER selects vllm.platforms._current_platform = CpuPlatform() and calls pytest.main(sys.argv[1:]). The negative name filter matched no test in this checkout; all 163 tests ran.

Tests are run with the prepared CUDA dependency environment on a GPU-less host, explicitly selecting CpuPlatform before pytest collection. The wrapper and logs are retained locally; no installed package files were modified.

Model/serving evidence and limits

The equivalent admission accounting was exercised as a local runtime adapter on B300 before this upstream refactor. Configuration: one EP8 prefill node using DeepEP high throughput, one EP8 decode node using DeepEP low latency, GLM-5.3 FP8 revision aca966e4e02791568aa6a4ced368624b3d897f42, BF16 KV, HiSparse on decode, index cache, NIXL pull and Mooncake CPU store. GPU KV was capped at 48 GiB/rank to force pressure. The tested vLLM source was f7f56f01d0f588f46c20035d3ab87cf16f25addf, with a separate complete-prefix NIXL adapter and the HiSparse layer-offset fix.

  • Before the admission adapter, the 2,048-request wave crashed a decode worker with the allocation error above.
  • With it, all 2,048 capacity requests completed. Peak active concurrency was 134/GPU with the remainder queued; 25 preemptions occurred in this intentional pressure wave.
  • The full suite recorded 3,760 completions and 32 intentional cancellations, zero request errors/empty streams, and healthy idle endpoints at the end.
  • The long-generation phase completed 256 requests while reloading 1,234.74 GiB of KV from CPU. There were no NIXL transfer/notification failures or failed required Mooncake GETs. The fixed-size prefill store rejected 15,019 optional PUT keys for lack of space.
  • No pathological gibberish was observed in the output screens and inspected samples. Long-request identifier retrieval was 255/256 versus 256/256 in a resident control, whose output cap was shorter (256 versus up to 1,536 tokens). Four capacity responses also copied their identifiers incorrectly. Exact output parity is not established; this is not a general accuracy evaluation.

Those GPU results validate the local adapter's behavior, not a model run of this new upstream commit. The final upstream implementation is covered by the regression tests above. No throughput improvement is claimed.

Duplicate-work check and scope

Reviewed issue #56699 and its comments, open PRs referencing it, and open PRs matching HiSparse/NIXL, admission, prefix, copies, and free blocks.

AI assistance (OpenAI Codex) was used for investigation, implementation, tests, and this description. Tests reported here were run by the agent. The user explicitly authorized this draft for review and assessment by vLLM collaborators. Human line-by-line review and independent validation are still pending; this draft is not presented as merge-ready.

Signed-off-by: S1ro1 <matej.sirovatka@gmail.com>
Co-authored-by: OpenAI Codex
@LucasWilkinson

Copy link
Copy Markdown
Contributor

@S1ro1 is this ready for review?

@MatthewBonanni

Copy link
Copy Markdown
Member

Thanks for the PR! Closing in favor of #59282 though, which should help admit requests in more cases

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working kv-cache-manager

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug][HiSparse] Decode engine dies with cudaErrorLaunchFailure in the host-mirror path under sustained P/D host imports

3 participants