Skip to content

[KV Offload] Size node-local shared regions by local_world_size - #53474

Open
nvyutwu wants to merge 1 commit into
vllm-project:mainfrom
nvyutwu:yutwu/kv-offload-local-world-size
Open

nvyutwu wants to merge 1 commit into
vllm-project:mainfrom
nvyutwu:yutwu/kv-offload-local-world-size

Conversation

@nvyutwu

@nvyutwu nvyutwu commented Aug 23, 2026

Copy link
Copy Markdown

Purpose

A shared CPU-offload mmap is node-local, but native offloading currently sizes its rows using the global worker count. TP8 across two nodes therefore reserves eight worker slots in each four-worker node's region, halving effective cache capacity at the same host-memory budget.

Size non-replicated rows using local_world_size, and assign slots using model-parallel rank modulo that size. Physical CUDA ordinals are unsuitable: devices 0 and 2 would both map to slot 0 with two local workers. Replicated layouts retain a single copy.

This change also validates the supported topology before allocation:

  • MP CPU-only offloading supports node-local sizing, including DP replicas with separate engine regions. The budget is per node, per DP replica.
  • PP and prefill-context parallelism are rejected because heterogeneous worker byte geometry is not negotiated.
  • Multi-worker Ray and external launchers are rejected. Ray topology is unavailable at this configuration boundary; external launchers additionally lack cross-worker completion aggregation.
  • Secondary tiers require each replica to fit on one node. The scheduler cannot access remote CPU mmap shards. DP replicas on different nodes remain allowed when each replica is node-local.

Secondary tiers mean storage beyond CPU memory, such as a filesystem or object store. This PR does not implement distributed secondary-tier transfers. It addresses the shared-region geometry discussed in #54415 and complements that separate protocol work.

Rebased onto 2a02f6efe319c885e3ccbcecde402e0028f9ec1e; that upstream revision still contains global sizing and physical-device slot assignment.

Validation

  • Regression tests cover device remapping, both node rank ranges, TP/DP local geometry, invalid sizes/ranks, unsupported backends and secondary-tier topology.
  • Final focused macOS source suites: 187 passed (existing cleanup-skip marker avoids a PyTorch macOS teardown crash).
  • Broader Linux source suites on one four-GPU GB200 host: 488 passed, one test-fixture failure from assuming a smaller host page size. The fixture now uses mmap.PAGESIZE; the affected suite rerun had 57 passed. Counts overlap.
  • CUDA offload worker suite: 39 passed, one skipped.
  • Real GPU-to-mmap-to-GPU tensor equality checks passed for TP2 on devices 0/2, modeled second-node TP4 ranks 2/3, and DP2×TP2 isolated cache regions on four GPUs. This harness uses threads and a thread barrier, so it does not validate a distributed launcher.
  • Tiny dummy-weight Llama on MP TP2 devices 0/2: three reloads after clearing GPU prefix cache each restored 96 cached tokens and reproduced identical output token IDs. This is a cache correctness check, not pretrained-model accuracy.
  • Applicable pre-commit hooks, including Ruff, mypy, configuration and documentation checks, passed; git diff --check passed.

Linux source test command:

.venv/bin/python -m pytest \
  tests/v1/kv_connector/unit/offloading_connector \
  tests/v1/kv_offload/test_factory.py \
  tests/v1/kv_offload/test_file_mapper.py \
  tests/v1/kv_offload/cpu/test_manager.py \
  tests/v1/kv_offload/tiering/test_factory.py \
  tests/v1/kv_offload/tiering/test_metrics.py -q
.venv/bin/python -m pytest tests/v1/kv_offload/cpu/test_gpu_worker.py -q

Validation used a Python source overlay with the cached container's compiled extensions. Subsequent two-node GB300 validation used real Qwen3-0.6B weights: TP4 across both nodes on physical devices 0/2 passed 12/12 CPU-cache reloads, and DP4×TP2 (two replicas per node, one API) passed 48/48 reloads targeting all four DP ranks. Every replay restored 304 cached tokens and exactly matched its 32 cold-reference output token IDs. CPU-to-GPU bytes increased 418,381,824 per engine. Both nodes verified the changed source-file hashes against this PR commit. The initial final-metric parser expected a newer metric name; independent verification of the saved raw responses and compatibility counters passed.

DCP remains unqualified in this test stack. Qwen TP4/DCP2 is invalid because TP must exceed its eight KV heads. Earlier TinyLlama comparisons mixed sequential cold requests with concurrent replays, so they did not control batch size.

A new two-node GB300 rerun used pretrained TinyLlama TP8/DCP2, FlashInfer, BF16, eager execution, temperature 0, seed 42, client concurrency 1, and server max_num_seqs=1 throughout. Four prompts each had three 32-token replays. With a GPU-warm reference request before the reloads, both the normal and hash-instrumented cases matched 6/12 cold outputs and 9/12 GPU-warm outputs; all reloads restored 320 cached tokens. An initial C1 run without the extra warm request matched 0/12. With CPU offload and prefix caching both disabled, DCP2 matched 10/12 recomputed outputs; the otherwise equivalent DCP1 control matched 12/12. These are replay comparisons, not model accuracy qualification.

The intrusive SHA-256 diagnostic audited every scheduled physical copy descriptor on all eight TP ranks across both nodes: 7,040 GPU-to-CPU store descriptors and 21,120 CPU-to-GPU load descriptors, zero mismatches. Every load matched its earlier GPU-before-store digest, CPU-before-load digest, and GPU-after-load digest; an independent validator reconstructed store history from the raw logs. Total audited load bytes were 86,507,520, consistent with the engine counter. This verifies the measured byte transfers, not logical-block selection or race freedom: the diagnostic synchronizes CUDA and can alter timing. No diagnostic instrumentation was added to the PR.

The DCP2 control demonstrates output differences without CPU offload, but does not root-cause them or establish an upstream DCP defect. The source overlay/cached compiled-extension combination remains a confound. No Kimi accuracy qualification was performed for this revised candidate. Earlier Kimi results reported in this PR's history apply to earlier code and are not presented as validation of this revision.

AI assistance

AI assistance was used to investigate, implement, review, and test this change. Human review remains required before merge.

@github-actions

Copy link
Copy Markdown

👋 Hi! Thank you for contributing to the vLLM project.

💬 Join our developer Slack at https://slack.vllm.ai to discuss your PR in #pr-reviews, coordinate on features in #feat- channels, or join special interest groups in #sig- channels.

PRs do not trigger a full CI run by default. Reviewers with write access and configured trusted contributors can comment /ci run for upstream CI or /amd-ci run for AMD CI only whenever CI signals are needed.

Once the PR is approved or has the ready label, the PR author can also use the corresponding /ci run, /ci retry, and /ci cancel commands, or their /amd-ci variants. New commits do not start upstream CI automatically.

If you have any questions, please reach out to us on Slack at https://slack.vllm.ai.

Agent Guidelines

IMPORTANT: 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.

🚀

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This pull request is from a fork — automated review is disabled. A repository maintainer can comment @claude review to run a one-time review.

@mergify

mergify Bot commented Sep 9, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @nvyutwu.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

@mergify mergify Bot added the needs-rebase label Sep 9, 2026
@nvyutwu
nvyutwu force-pushed the yutwu/kv-offload-local-world-size branch from f1e1008 to f68947d Compare September 10, 2026 05:30
@mergify

mergify Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Documentation preview: https://vllm--53474.org.readthedocs.build/en/53474/

@mergify mergify Bot added documentation Improvements or additions to documentation and removed needs-rebase labels Sep 10, 2026
@mergify

mergify Bot commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

This pull request has merge conflicts that must be resolved before it can be
merged. Please rebase the PR, @nvyutwu.

https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/syncing-a-fork

…sions

Size shared CPU offload rows by local_world_size and assign worker slots
by model-parallel rank. Preserve per-node, per-DP-replica capacity and
reject unsupported launcher, PP/PCP, and remote secondary-tier topologies.

Refresh on main while retaining upstream HiSparse group selection and tests.

Generated with [Devin](https://devin.ai)

Co-authored-by: Codex <codex@openai.com>
Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Signed-off-by: Yuting Wu (DLAlgo) <yutwu@nvidia.com>
@nvyutwu
nvyutwu force-pushed the yutwu/kv-offload-local-world-size branch from f68947d to d7ba4fd Compare September 17, 2026 00:08
@mergify mergify Bot removed the needs-rebase label Sep 17, 2026
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 kv-connector

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant