Skip to content

Commit 3d077f9

Browse files
authored
[BugFix][KV Pool] Gate Memcache lazy init by protocol and make register buffer default (vllm-project#12064)
### What this PR does / why we need it? Memcache initialization currently uses the Ascend device type as a proxy for the configured transport protocol. This is no longer accurate because buffer registration decisions are handled by `store.register_buffer()`, while lazy initialization is only required by the `device_sdma` protocol. This PR: - removes the A2-specific `all_gather` and device-type checks from `MemcacheBackend`; - enables requested lazy initialization only when `MMC_LOCAL_CONFIG_PATH` sets `ock.mmc.local_service.protocol` to `device_sdma`; - requires `MMC_LOCAL_CONFIG_PATH`, handles protocol whitespace and comments, and surfaces missing or unreadable configuration file errors; - forwards buffer registration decisions to Memcache and defers pending registrations until a lazy store is initialized. ### Does this PR introduce _any_ user-facing change? Yes. Memcache lazy initialization is now selected by the configured `device_sdma` protocol instead of the Ascend device type. Other protocols initialize the store eagerly. ### How was this patch tested? - All repository pre-commit hooks passed, including ruff, formatting, spelling, custom Python checks, and commit sign-off validation. - Python syntax compilation passed for the modified backend. - Targeted checks passed for protocol whitespace, comments, missing environment variables, missing-file error propagation, `device_sdma`/`device_rdma` selection, and deferred buffer registration after lazy initialization. - vLLM version: v0.25.1 - vLLM main: vllm-project/vllm@fe784ff Signed-off-by: Pz1116 <zpbzpb123123@gmail.com>
1 parent b2f683c commit 3d077f9

2 files changed

Lines changed: 24 additions & 22 deletions

File tree

tests/ut/distributed/ascend_store/test_backend.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -600,9 +600,7 @@ def _make_backend(self):
600600
# Set internal state to avoid lazy init logic during tests
601601
backend._lazy_init = False
602602
backend._store_initialized = True
603-
backend._is_a2 = False
604-
backend._registered_buffers = None
605-
backend._buffers_registered = False
603+
backend._pending_buffers = None
606604
return backend
607605

608606
def test_exists(self):
@@ -612,7 +610,6 @@ def test_exists(self):
612610

613611
def test_register_buffer(self):
614612
b = self._make_backend()
615-
b._is_a2 = True
616613
b.register_buffer([100], [200])
617614
b.store.register_buffer.assert_called_once()
618615

vllm_ascend/distributed/kv_transfer/kv_pool/ascend_store/backend/memcache_backend.py

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
# Standard
2+
import os
23
import threading
34
import time
45
from enum import Enum
@@ -10,7 +11,22 @@
1011
from vllm.logger import logger
1112

1213
from vllm_ascend.distributed.kv_transfer.kv_pool.ascend_store.backend.backend import Backend
13-
from vllm_ascend.utils import AscendDeviceType, get_ascend_device_type
14+
15+
16+
def _is_device_sdma() -> bool:
17+
config_path = os.getenv("MMC_LOCAL_CONFIG_PATH")
18+
if not config_path:
19+
raise ValueError("The environment variable 'MMC_LOCAL_CONFIG_PATH' is not set.")
20+
with open(config_path, encoding="utf-8") as config_file:
21+
for line in config_file:
22+
line = line.strip()
23+
if not line or line.startswith(("#", ";")):
24+
continue
25+
key, separator, value = line.partition("=")
26+
if separator and key.strip() == "ock.mmc.local_service.protocol":
27+
return value.strip() == "device_sdma"
28+
return False
29+
1430

1531
MEMCACHE_THREAD_START_WAIT_S = 0.1
1632

@@ -32,14 +48,12 @@ def __init__(
3248
):
3349
self.local_rank = local_rank if local_rank is not None else get_world_group().local_rank
3450
self._init_bm = init_bm
35-
self._is_a2 = get_ascend_device_type() in {AscendDeviceType.A2}
36-
self._lazy_init = lazy_init and not self._is_a2
51+
self._lazy_init = lazy_init and _is_device_sdma()
3752

3853
self.store: Any | None = None
3954
self._store_initialized = False
4055
self._store_init_lock = threading.Lock()
41-
self._registered_buffers: tuple[list[int], list[int]] | None = None
42-
self._buffers_registered = False
56+
self._pending_buffers: tuple[list[int], list[int]] | None = None
4357

4458
if not self._lazy_init:
4559
self.store = self._setup_store()
@@ -68,11 +82,6 @@ def _setup_store(self):
6882
"to run vLLM with MemcacheConnector."
6983
) from e
7084

71-
if self._init_bm and self._is_a2:
72-
tmp_tensor = torch.zeros(1, device="npu")
73-
output_tensor_list = [torch.empty_like(tmp_tensor) for _ in range(torch.distributed.get_world_size())]
74-
torch.distributed.all_gather(output_tensor_list, tmp_tensor, group=get_world_group().device_group)
75-
7685
store = DistributedObjectStore()
7786

7887
try:
@@ -108,21 +117,17 @@ def set_device(self):
108117
torch.npu.set_device(device)
109118

110119
def register_buffer(self, ptrs: list[int], sizes: list[int]):
111-
self._registered_buffers = (list(ptrs), list(sizes))
120+
self._pending_buffers = (list(ptrs), list(sizes))
112121
self._register_buffers_if_needed()
113122

114123
def _register_buffers_if_needed(self):
115-
if not self._is_a2:
116-
return
117-
if self._registered_buffers is None or self._buffers_registered:
118-
return
119-
if not self._store_initialized:
124+
if self._pending_buffers is None or not self._store_initialized:
120125
return
121126
assert self.store is not None
122-
ptrs, sizes = self._registered_buffers
127+
ptrs, sizes = self._pending_buffers
123128
for ptr, size in zip(ptrs, sizes):
124129
self.store.register_buffer(ptr, size)
125-
self._buffers_registered = True
130+
self._pending_buffers = None
126131

127132
def exists(self, keys: list[str]) -> list[int]:
128133
if self._lazy_init and not self._store_initialized:

0 commit comments

Comments
 (0)