[KV Offload] Define clean backend configuration boundary - #48150
Conversation
|
Thanks @Change72 ! As a principle, the |
Define model- and group-level offloading configuration structs in kv_offload. Build them in OffloadingConnector, pass raw vLLM configs directly to connector scheduler and worker components, and construct backend specs from the normalized config. This refactor has no intended runtime behavior change. Co-authored-by: Codex <codex@openai.com> Signed-off-by: Change72 <changg@nvidia.com>
4a9b6fc to
b5c2ba2
Compare
Remove unused raw-config retention from connector components. Resolve relative imports and narrow the TYPE_CHECKING allowlist in the dependency sentinel, and assert plugin config identity through the public spec boundary. Co-authored-by: Codex <codex@openai.com> Signed-off-by: Change72 <changg@nvidia.com>
|
Thanks @orozery — I reworked the PR around that boundary:
One scope question: |
orozery
left a comment
There was a problem hiding this comment.
Thanks @Change72 ! Great work!
One scope question:
cpu/manager.pyandtiering/manager.pyalready import connector metrics at runtime. Should I clean those up in this PR or leave them for a follow-up?
I actually think it's fine to leave it as is for now.
We have some external dependencies which I think are fine as they are minimal and should be stable.
e.g. KVConnectorStats, kv event mediums.
| @dataclass(frozen=True) | ||
| class OffloadingGroupConfig: | ||
| """Normalized configuration for one KV cache group.""" | ||
|
|
||
| block_size: int | ||
| gpu_block_size: int | ||
| layer_names: tuple[str, ...] | ||
| is_non_mla_full_attention: bool | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class OffloadingConfig: | ||
| """Model-level configuration for a native offloading backend.""" | ||
|
|
||
| groups: tuple[OffloadingGroupConfig, ...] | ||
| hash_block_size: int | ||
| block_size_factor: int | ||
| num_gpu_blocks: int | ||
| worker_kv_bytes_per_gpu_block: int | ||
| world_size: int | ||
| enable_kv_cache_events: bool | ||
| extra_config: Mapping[str, Any] | ||
| model_name: str | ||
| kv_cache_dtype: str | ||
| namespace_block_size: int | ||
| tp_size: int | ||
| pp_size: int | ||
| pcp_size: int | ||
| dcp_size: int | ||
| rank: int | ||
| use_v2_model_runner: bool | ||
| engine_id: str | None |
There was a problem hiding this comment.
Suggesting some changes.
Here are the adaptations needed:
- namespace_block_size dropped → FileMapper uses cache.hash_block_size instead.
- Per-group block_size dropped → FileMapper uses tokens_per_block in the namespace hash.
- parallel_agnostic pre-computed → FileMapper no longer decides this itself.
- num_gpu_blocks dropped → Consumers check worker_kv_bytes_per_block == 0 as the "no blocks" sentinel.
- engine_id made non-optional → Builder asserts it exists (offloading is always active when this config is constructed).
| @dataclass(frozen=True) | |
| class OffloadingGroupConfig: | |
| """Normalized configuration for one KV cache group.""" | |
| block_size: int | |
| gpu_block_size: int | |
| layer_names: tuple[str, ...] | |
| is_non_mla_full_attention: bool | |
| @dataclass(frozen=True) | |
| class OffloadingConfig: | |
| """Model-level configuration for a native offloading backend.""" | |
| groups: tuple[OffloadingGroupConfig, ...] | |
| hash_block_size: int | |
| block_size_factor: int | |
| num_gpu_blocks: int | |
| worker_kv_bytes_per_gpu_block: int | |
| world_size: int | |
| enable_kv_cache_events: bool | |
| extra_config: Mapping[str, Any] | |
| model_name: str | |
| kv_cache_dtype: str | |
| namespace_block_size: int | |
| tp_size: int | |
| pp_size: int | |
| pcp_size: int | |
| dcp_size: int | |
| rank: int | |
| use_v2_model_runner: bool | |
| engine_id: str | None | |
| @dataclass(frozen=True) | |
| class OffloadingGroupConfig: | |
| # Total token span covered by one block across all workers | |
| # (accounts for context parallelism). | |
| tokens_per_block: int | |
| # Layer names belonging to this group. | |
| layer_names: tuple[str, ...] | |
| @dataclass(frozen=True) | |
| class OffloadingModelConfig: | |
| # Model identifier (e.g. HuggingFace model path). | |
| name: str | |
| # KV cache data type (e.g. "float16"). | |
| dtype: str | |
| @dataclass(frozen=True) | |
| class OffloadingCacheConfig: | |
| # Tokens per block hash. | |
| hash_block_size: int | |
| # Blocks per offload key. | |
| blocks_per_key: int | |
| @dataclass(frozen=True) | |
| class OffloadingParallelConfig: | |
| # Worker index in [0, world_size). 0 on the scheduler side. | |
| rank: int | |
| # Total number of workers. | |
| world_size: int | |
| # Tensor parallel size. | |
| tp_size: int | |
| # Pipeline parallel size. | |
| pp_size: int | |
| # Prefill context parallel size. | |
| pcp_size: int | |
| # Decode context parallel size. | |
| dcp_size: int | |
| # True when concatenating a block's data across all workers yields | |
| # the same result regardless of the parallelism configuration. | |
| is_parallelism_agnostic: bool | |
| @dataclass(frozen=True) | |
| class OffloadingConfig: | |
| groups: tuple[OffloadingGroupConfig, ...] | |
| # KV bytes stored by one worker per block. | |
| worker_kv_bytes_per_block: int | |
| # Whether the scheduler emits KV cache events. When true, | |
| # the offloading backend should emit events as well. | |
| enable_kv_cache_events: bool | |
| # Offloading-specific configuration from kv_connector_extra_config. | |
| extra_config: Mapping[str, Any] | |
| # Unique identifier for this engine, distinct per DP rank. | |
| engine_id: str | |
| model: OffloadingModelConfig | |
| cache: OffloadingCacheConfig | |
| parallel: OffloadingParallelConfig |
| assert cls is TieringOffloadingSpec | ||
|
|
||
|
|
||
| def test_kv_offload_config_boundary_has_no_reverse_runtime_imports(): |
There was a problem hiding this comment.
This test is nice, but it's kind of cumbersome, and also hard to maintain with all the paths hard-coding consts.
I suggest we remove it.
Adopt the reviewer-suggested nested config shape: model-, cache-, and parallel-level sub-configs with tokens_per_block, blocks_per_key, and worker_kv_bytes_per_block (0 = no blocks). The parallelism-agnostic predicate is precomputed by the connector translation, the file namespace records the resolved hash granularity, engine_id becomes required, and the import-guard test is removed. Signed-off-by: Change72 <changg@nvidia.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Thanks @orozery — applied all of it: Adopted your struct suggested shape and removed the import-guard test. (from claude:) |
orozery
left a comment
There was a problem hiding this comment.
(from claude:)
One pre-existing inconsistency surfaced while adapting this (not introduced here, and left as-is): tokens_per_block applies the DCP×PCP factor to every group, faithful to the old gpu_block_size computation — but resolve_kv_cache_block_sizes deliberately leaves Mamba groups unscaled ("Mamba groups keep their full per-rank state and are not scaled"). So for Mamba-hybrid + context-parallel setups the offload path disagrees with the core resolver, as it did before. Happy to fix that here or in a follow-up — your call.
Let's leave it as it is.
| "spec_name": "CPUOffloadingSpec", | ||
| "cpu_bytes_to_use": 1, |
There was a problem hiding this comment.
Can we revert back to generating a mocked spec instead of building a real one?
| # Blocks per offload key. | ||
| blocks_per_key: int |
There was a problem hiding this comment.
Re-thinking this, we use "block" as the unit being stored in the accelerated (GPU) hardware.
For the unit being offloaded, we use "key", which is confusing.
Claude suggested we use "chunk" instead.
It would be good to rename block_size_factor to blocks_per_chunk throughout the code.
Can also rename block_size -> tokens_per_blocks
offloaded_block_size -> tokens_per_chunk
hash_block_size -> tokens_per_hash
hash_block_size_factor -> hashes_per_chunk
src_block_size_factor -> src_blocks_per_chunk
dst_block_size_factor -> dst_blocks_per_chunk
sub_block_size -> block_page_size (gpu_worker.py)
sub_block_size -> tokens_per_hash (events.py)
full_attn_offloaded_block_sizes -> full_attn_tokens_per_chunk
offload_block_idx -> chunk_idx
gpu_blocks_per_file -> blocks_per_file
kv_bytes_per_offloaded_block -> kv_bytes_per_chunk
| # Blocks per offload key. | |
| blocks_per_key: int | |
| # Blocks coalesced into one offload chunk. | |
| blocks_per_chunk: int |
There was a problem hiding this comment.
we use "key", which is confusing.
Agreed. tokens_per_blocks and hash_block_size were also confused for me in the previous commit.
block_size -> tokens_per_blocks
offloaded_block_size -> tokens_per_chunk
hash_block_size -> tokens_per_hash
are more clear. Will fix
There was a problem hiding this comment.
I made a typo it should be tokens_per_block not tokens_per_blocks.
Co-authored-by: Or Ozeri <or@ozery.com> Signed-off-by: Chang Guo <cguo51@asu.edu>
Co-authored-by: Or Ozeri <or@ozery.com> Signed-off-by: Chang Guo <cguo51@asu.edu>
Per review: the offloaded unit is now consistently called a chunk. Rename blocks_per_key/block_size_factor to blocks_per_chunk, hash_block_size to tokens_per_hash, offloaded_block_size to tokens_per_chunk, kv_bytes_per_offloaded_block to kv_bytes_per_chunk, and related identifiers, including the namespace JSON keys (on-disk digests change). The FileMapper test helper builds a mocked spec from a plain OffloadingConfig, and the parallelism-agnostic predicate tests move next to the translation they exercise. The user-facing extra_config["block_size"] key is unchanged. Signed-off-by: Change72 <changg@nvidia.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Thanks @Change72 ! |
Per review: local variables and the scheduler-side group config field missed by the previous rename pass. Signed-off-by: Change72 <changg@nvidia.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ut-config-refactor
The merge with main brought vllm-project#47636's P2P side-channel port offset, which read the removed OffloadingSpec.vllm_config. Expose data_parallel_index on OffloadingParallelConfig and read it through the translated config instead. Also rename the remaining chunk-valued scheduler identifiers (tokens_per_chunk locals, chunk indices, num_hit_chunks, storable_chunks, sliding-window sizes in chunks) and update the P2P fixture to the translated-config shape. Signed-off-by: Change72 <changg@nvidia.com> Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Rename scheduler locals that count or index offload chunks while preserving true GPU and cache block terminology. Update the corresponding test reference and add coverage that nonzero data_parallel_index survives connector config translation. Signed-off-by: Change72 <changg@nvidia.com> Co-authored-by: OpenAI Codex <noreply@openai.com>
|
All requested changes are done:
|
orozery
left a comment
There was a problem hiding this comment.
Keep up the good work! :)
…adapt MockOffloadingSpec to OffloadingSpec single-config API Root cause: upstream vLLM #48150 replaced OffloadingSpec.__init__(vllm_config, kv_cache_config) with a single OffloadingConfig; create_spec now calls spec_cls(config). Upstream: vllm-project/vllm#48150 Fix: MockOffloadingSpec takes OffloadingConfig; rename GroupOffloadConfig field asserts (gpu_block_size->tokens_per_block, offloaded_block_size->tokens_per_chunk). Signed-off-by: Paweł Olejniczak <pawelx.olejniczak@intel.com>
…adapt MockOffloadingSpec to OffloadingSpec single-config API Root cause: upstream vLLM #48150 replaced OffloadingSpec.__init__(vllm_config, kv_cache_config) with a single OffloadingConfig; create_spec now calls spec_cls(config). Upstream: vllm-project/vllm#48150 Fix: MockOffloadingSpec takes OffloadingConfig; rename GroupOffloadConfig field asserts (gpu_block_size->tokens_per_block, offloaded_block_size->tokens_per_chunk). Signed-off-by: Paweł Olejniczak <pawelx.olejniczak@intel.com>
…ead offloading kv_cache_config from worker not spec Root cause: vLLM PR #48150 moved kv_cache_config off CPUOffloadingSpec onto OffloadingConnectorWorker (self.kv_cache_config). Upstream: vllm-project/vllm#48150 (a9531edfa63197dc083cf60be85e777c64fbfb60) Fix: HPU register_kv_caches reads self.kv_cache_config instead of self.spec.kv_cache_config. Signed-off-by: Paweł Olejniczak <pawelx.olejniczak@intel.com>
…ename HPU offloading worker init kwarg to blocks_per_chunk Root cause: vLLM PR #48150 renamed the CPU/GPU page-size ratio kwarg on CPUOffloadingWorker.__init__ from block_size_factor to blocks_per_chunk; upstream create_worker now calls with blocks_per_chunk=, but the gaudi HPU override CPUOffloadingWorker_init_ still declared block_size_factor -> TypeError at EngineCore startup. Upstream: vllm-project/vllm#48150 (a9531edfa63197dc083cf60be85e777c64fbfb60) Fix: rename the HPU override parameter to blocks_per_chunk (semantics unchanged; gpu_worker.py computes cpu_page_size = gpu_page_size * blocks_per_chunk) and pass it through to the HPU SingleDirectionOffloadingHandler as block_size_factor. Signed-off-by: Paweł Olejniczak <pawelx.olejniczak@intel.com>
…t#48150) Signed-off-by: Change72 <changg@nvidia.com> Signed-off-by: Chang Guo <cguo51@asu.edu> Co-authored-by: Codex <codex@openai.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Or Ozeri <or@ozery.com> Co-authored-by: OpenAI Codex <noreply@openai.com>
…adapt MockOffloadingSpec to OffloadingSpec single-config API Root cause: upstream vLLM #48150 replaced OffloadingSpec.__init__(vllm_config, kv_cache_config) with a single OffloadingConfig; create_spec now calls spec_cls(config). Upstream: vllm-project/vllm#48150 Fix: MockOffloadingSpec takes OffloadingConfig; rename GroupOffloadConfig field asserts (gpu_block_size->tokens_per_block, offloaded_block_size->tokens_per_chunk). Signed-off-by: Paweł Olejniczak <pawelx.olejniczak@intel.com>
…ead offloading kv_cache_config from worker not spec Root cause: vLLM PR #48150 moved kv_cache_config off CPUOffloadingSpec onto OffloadingConnectorWorker (self.kv_cache_config). Upstream: vllm-project/vllm#48150 (a9531edfa63197dc083cf60be85e777c64fbfb60) Fix: HPU register_kv_caches reads self.kv_cache_config instead of self.spec.kv_cache_config. Signed-off-by: Paweł Olejniczak <pawelx.olejniczak@intel.com>
…ename HPU offloading worker init kwarg to blocks_per_chunk Root cause: vLLM PR #48150 renamed the CPU/GPU page-size ratio kwarg on CPUOffloadingWorker.__init__ from block_size_factor to blocks_per_chunk; upstream create_worker now calls with blocks_per_chunk=, but the gaudi HPU override CPUOffloadingWorker_init_ still declared block_size_factor -> TypeError at EngineCore startup. Upstream: vllm-project/vllm#48150 (a9531edfa63197dc083cf60be85e777c64fbfb60) Fix: rename the HPU override parameter to blocks_per_chunk (semantics unchanged; gpu_worker.py computes cpu_page_size = gpu_page_size * blocks_per_chunk) and pass it through to the HPU SingleDirectionOffloadingHandler as block_size_factor. Signed-off-by: Paweł Olejniczak <pawelx.olejniczak@intel.com>
…adapt MockOffloadingSpec to OffloadingSpec single-config API Root cause: upstream vLLM #48150 replaced OffloadingSpec.__init__(vllm_config, kv_cache_config) with a single OffloadingConfig; create_spec now calls spec_cls(config). Upstream: vllm-project/vllm#48150 Fix: MockOffloadingSpec takes OffloadingConfig; rename GroupOffloadConfig field asserts (gpu_block_size->tokens_per_block, offloaded_block_size->tokens_per_chunk). Signed-off-by: Paweł Olejniczak <pawelx.olejniczak@intel.com>
…ead offloading kv_cache_config from worker not spec Root cause: vLLM PR #48150 moved kv_cache_config off CPUOffloadingSpec onto OffloadingConnectorWorker (self.kv_cache_config). Upstream: vllm-project/vllm#48150 (a9531edfa63197dc083cf60be85e777c64fbfb60) Fix: HPU register_kv_caches reads self.kv_cache_config instead of self.spec.kv_cache_config. Signed-off-by: Paweł Olejniczak <pawelx.olejniczak@intel.com>
…ename HPU offloading worker init kwarg to blocks_per_chunk Root cause: vLLM PR #48150 renamed the CPU/GPU page-size ratio kwarg on CPUOffloadingWorker.__init__ from block_size_factor to blocks_per_chunk; upstream create_worker now calls with blocks_per_chunk=, but the gaudi HPU override CPUOffloadingWorker_init_ still declared block_size_factor -> TypeError at EngineCore startup. Upstream: vllm-project/vllm#48150 (a9531edfa63197dc083cf60be85e777c64fbfb60) Fix: rename the HPU override parameter to blocks_per_chunk (semantics unchanged; gpu_worker.py computes cpu_page_size = gpu_page_size * blocks_per_chunk) and pass it through to the HPU SingleDirectionOffloadingHandler as block_size_factor. Signed-off-by: Paweł Olejniczak <pawelx.olejniczak@intel.com>
…ename HPU offloading worker init kwarg to blocks_per_chunk Root cause: vLLM PR #48150 renamed the CPU/GPU page-size ratio kwarg on CPUOffloadingWorker.__init__ from block_size_factor to blocks_per_chunk; upstream create_worker now calls with blocks_per_chunk=, but the gaudi HPU override CPUOffloadingWorker_init_ still declared block_size_factor -> TypeError at EngineCore startup. Upstream: vllm-project/vllm#48150 Fix: rename the HPU override parameter to blocks_per_chunk (semantics unchanged; gpu_worker.py computes cpu_page_size = gpu_page_size * blocks_per_chunk) and pass it through to the HPU SingleDirectionOffloadingHandler as block_size_factor. Signed-off-by: Paweł Olejniczak <pawelx.olejniczak@intel.com>
…roject#48959) update_state_after_alloc bounds the pending (to-load) GPU blocks of a sliding-window group by sliding_window_size_in_chunks * blocks_per_chunk. When the sliding window is a multiple of the chunk size (e.g. DeepSeek-V4: 4096-token window, 256-token chunk) this equals cdiv(sliding_window, gpu_block_size) exactly, leaving no headroom for an unaligned window start. The live SWA window is sliding_window - 1 tokens starting at an arbitrary offset; single_type_kv_cache_manager floors the null-placeholder prefix to whole GPU blocks (never to chunks), so the pending span can intersect one extra physical GPU block: cdiv(sliding_window + gpu_block_size - 1, gpu_block_size). For the production geometry that is 129 vs an allowed 128, which fatally aborts EngineCore under ordinary long-agent traffic. Bound by the exact physical span instead, computed per group at config-build time so the correction is scoped to genuine sliding-window groups and Mamba keeps its single-state (blocks_per_chunk) bound. Reported on vllm-project#48959 by coltonottley; their fork fix does not apply here (pre-vllm-project#48150 field names). Validated by unit test only: CPU KV offload is opt-in and no serving gate exercises it. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
…t#48150) Signed-off-by: Change72 <changg@nvidia.com> Signed-off-by: Chang Guo <cguo51@asu.edu> Co-authored-by: Codex <codex@openai.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Or Ozeri <or@ozery.com> Co-authored-by: OpenAI Codex <noreply@openai.com>
…ename HPU offloading worker init kwarg to blocks_per_chunk Root cause: vLLM PR #48150 renamed the CPU/GPU page-size ratio kwarg on CPUOffloadingWorker.__init__ from block_size_factor to blocks_per_chunk; upstream create_worker now calls with blocks_per_chunk=, but the gaudi HPU override CPUOffloadingWorker_init_ still declared block_size_factor -> TypeError at EngineCore startup. Upstream: vllm-project/vllm#48150 Fix: rename the hpu override parameter to blocks_per_chunk (semantics unchanged; gpu_worker.py computes cpu_page_size = gpu_page_size * blocks_per_chunk) and pass it through to the HPU SingleDirectionOffloadingHandler as block_size_factor. Signed-off-by: Paweł Olejniczak <pawelx.olejniczak@intel.com>
…ename HPU offloading worker init kwarg to blocks_per_chunk Root cause: vLLM PR #48150 renamed the CPU/GPU page-size ratio kwarg on CPUOffloadingWorker.__init__ from block_size_factor to blocks_per_chunk; upstream create_worker now calls with blocks_per_chunk=, but the gaudi HPU override CPUOffloadingWorker_init_ still declared block_size_factor -> TypeError at EngineCore startup. Upstream: vllm-project/vllm#48150 Fix: rename the HPU override parameter to blocks_per_chunk (semantics unchanged; gpu_worker.py computes cpu_page_size = gpu_page_size * blocks_per_chunk) and pass it through to the HPU SingleDirectionOffloadingHandler as block_size_factor. Signed-off-by: Paweł Olejniczak <pawelx.olejniczak@intel.com>
…adapt MockOffloadingSpec to OffloadingSpec single-config API (#1621) ## Root cause Upstream vLLM PR #48150 collapsed `OffloadingSpec.__init__(vllm_config, kv_cache_config)` into a single `OffloadingConfig` argument, and `create_spec` now calls `spec_cls(config)`. The gaudi unit-test `MockOffloadingSpec` still declared the old two-argument constructor, so every `test_scheduler.py` collection raised `TypeError: MockOffloadingSpec.__init__() missing 1 required positional argument: 'kv_cache_config'`. The same PR renamed `GroupOffloadConfig` fields (`gpu_block_size` -> `tokens_per_block`, `offloaded_block_size` -> `tokens_per_chunk`). ## Upstream PR vllm-project/vllm#48150 Replaced the two-argument OffloadingSpec constructor with a single OffloadingConfig and renamed the GroupOffloadConfig block-size fields. ## Fix Update `MockOffloadingSpec.__init__` to accept a single `OffloadingConfig` and forward it to `super().__init__(config)`, import `OffloadingConfig`, drop the now-unused `VllmConfig` import, and rename the `RequestRunner` assertions to the new `tokens_per_block` / `tokens_per_chunk` field names. --------- Signed-off-by: Paweł Olejniczak <pawelx.olejniczak@intel.com>
Purpose
Part of #47929.
This PR defines plain offloading configuration structs in
vllm/v1/kv_offloadand moves the existingKVCacheSpecandKVCacheConfigparsing for block geometry, CPU sizing inputs, and file identity into the offloading connector, which translates the raw configs into those structs. The struct shape (model-, cache-, and parallel-level sub-configs withtokens_per_block,blocks_per_chunk, and a precomputed parallelism-agnostic flag) follows the review suggestion.OffloadingSpecplugin constructor to a single translatedOffloadingConfigargument (a breaking change for external specs loaded viaspec_module_path; the migration is mechanical, and a transition period accepting both signatures can be added if preferred).blocks_per_chunk,tokens_per_chunk,tokens_per_hash,tokens_per_block, applied to config, spec, scheduler, FileMapper, and tests. Values are preserved; only names change.This refactor has no intended runtime behavior change, with one review-requested exception: the FileMapper namespace now records the resolved hash granularity, the context-parallel-scaled per-group block sizes, and the renamed identity keys. All FS/OBJ namespace digests therefore change: existing on-disk caches are safely cold-missed, and mixed-version P2P peers fail closed on the config-fingerprint mismatch. The breaking change to the experimental plugin surface covers the renamed config/spec/FileMapper fields as well, not just the constructor. CPU sizing is unchanged, and this PR does not implement MLA replica deduplication.
This ownership split was requested in #47929. It establishes connector-owned parsing helpers that the next PR can extend on the scheduler side to infer replicated MLA layouts from
KVCacheSpec.Duplicate-work check
I checked the issue comments and searched open PRs by issue number and area keywords. No other open PR references #47929 or implements this parsing move.
The closest related work—#42374, #46954, #44865, and #38261—covers core KV representation, canonical layout metadata, transfer descriptors, or hybrid planning rather than this ownership refactor.
Test Plan
tests/v1/kv_offloadsuite.Test Result
On NVIDIA L4 with PyTorch
2.11.0+cu128and CUDA 12.8:Result:
34 passed.Result:
46 passed, 2 skipped.The P2P manager tests (including the data-parallel port-offset cases from #47636, adapted to the translated config) pass:
60 passed.The full
tests/v1/kv_offloadsuite was additionally compared against the latest-main merge-base on the same host: the failing cases are identical pre-existing environment-dependent tests on that setup — the change introduces no new failures (347 passed, 2 skippedotherwise).Changed-file pre-commit, manual
mypy-3.12, andgit diff --checkalso passed.AI Assistance
AI assistance was used for implementation and review.