[XPU][UT] Fix OOM and skip graph case (#49287)
Signed-off-by: mayuyuace <qiming1.zhang@intel.com> Signed-off-by: Qiming Zhang <qiming1.zhang@intel.com> Co-authored-by: Kunshang Ji <kunshang.ji@intel.com>
Qiming Zhang committed
Aug 17, 2026 at 18:47 UTC
f4b161d7fca438bfe29509984759be1943a5aa88
6 files changed
+47
-22
tests/conftest.py
+26
-11
@@ -914,13 +914,13 @@ class HfRunner:
914
return self
915
916
def __exit__(self, exc_type, exc_value, traceback):
917
- from tests.utils import wait_for_rocm_memory_to_settle
917
+ from tests.utils import wait_for_memory_to_settle
918
919
del self.model
920
cleanup_dist_env_and_memory()
921
# ROCm frees VRAM lazily; wait so a runner started right after this HF
922
# model exits does not OOM on its startup memory guard.
923
- wait_for_rocm_memory_to_settle(
923
+ wait_for_memory_to_settle(
924
threshold_ratio=getattr(self, "threshold_ratios", None)
925
)
926
if hasattr(self, "threshold_ratios"):
@@ -998,9 +998,24 @@ class VllmRunner:
998
# V1 startup requires free_memory >= total * gpu_memory_utilization.
999
# ROCm CI can hand a test a device that is still lazily releasing
1000
# VRAM from a previous process, so wait before constructing LLM.
1001
- from tests.utils import wait_for_rocm_memory_to_settle
1002
-
1003
- wait_for_rocm_memory_to_settle(threshold_ratio=1.0 - gpu_memory_utilization)
1001
+ from tests.utils import wait_for_memory_to_settle
1002
+
1003
+ wait_for_memory_to_settle(threshold_ratio=1.0 - gpu_memory_utilization)
1004
+ elif current_platform.is_xpu():
1005
+ # The XPU/oneAPI runtime keeps ~1 GiB of context resident in the
1006
+ # parent pytest process for its whole lifetime (grown by in-process
1007
+ # HfRunner models), and distributed tests additionally allocate a
1008
+ # CCL context in the engine subprocess. The default utilization of
1009
+ # 0.92 leaves too little headroom for both, so lower it on XPU when
1010
+ # the caller did not request an explicit value.
1011
+ if "gpu_memory_utilization" not in kwargs:
1012
+ kwargs["gpu_memory_utilization"] = 0.9
1013
+ gpu_memory_utilization = kwargs["gpu_memory_utilization"]
1014
+ # XPU (Level Zero) can also release device memory lazily after a
1015
+ # previous engine shuts down, so wait before constructing LLM.
1016
+ from tests.utils import wait_for_memory_to_settle
1017
+
1018
+ wait_for_memory_to_settle(threshold_ratio=1.0 - gpu_memory_utilization)
1019
1020
with init_ctx:
1021
self.llm = LLM(
@@ -1326,14 +1341,14 @@ class VllmRunner:
1341
def __enter__(self):
1342
return self
1343
1329
- def _wait_for_rocm_memory_release(self, gpu_memory_utilization: float) -> None:
1330
- from tests.utils import wait_for_rocm_memory_to_settle
1344
+ def _wait_for_memory_release(self, gpu_memory_utilization: float) -> None:
1345
+ from tests.utils import wait_for_memory_to_settle
1346
1347
# V1 startup requires free_memory >= total * gpu_memory_utilization.
1348
# Wait for the complementary used-memory ratio so the next runner does
1349
# not fail the startup guard immediately after this runner exits. The
1350
# wait is bounded so cleanup failures fail this test instead of hanging.
1336
- wait_for_rocm_memory_to_settle(threshold_ratio=1.0 - gpu_memory_utilization)
1351
+ wait_for_memory_to_settle(threshold_ratio=1.0 - gpu_memory_utilization)
1352
1353
def __exit__(self, exc_type, exc_value, traceback):
1354
# Explicitly shutdown the engine core to release GPU resources
@@ -1359,7 +1374,7 @@ class VllmRunner:
1374
del self.llm
1375
torch._dynamo.reset()
1376
cleanup_dist_env_and_memory()
1362
- self._wait_for_rocm_memory_release(gpu_memory_utilization)
1377
+ self._wait_for_memory_release(gpu_memory_utilization)
1378
1379
1380
@pytest.fixture(scope="session")
@@ -1746,7 +1761,7 @@ def clean_gpu_memory_between_tests():
1761
1762
import gc
1763
1749
- from tests.utils import wait_for_gpu_memory_to_clear, wait_for_rocm_memory_to_settle
1764
+ from tests.utils import wait_for_gpu_memory_to_clear, wait_for_memory_to_settle
1765
1766
num_gpus = torch.accelerator.device_count()
1767
@@ -1755,7 +1770,7 @@ def clean_gpu_memory_between_tests():
1770
return
1771
try:
1772
if current_platform.is_rocm():
1758
- wait_for_rocm_memory_to_settle()
1773
+ wait_for_memory_to_settle()
1774
else:
1775
wait_for_gpu_memory_to_clear(
1776
devices=list(range(num_gpus)),
tests/models/language/generation/test_hybrid.py
+3
@@ -9,6 +9,7 @@ import pytest
9
from tests.models.registry import HF_EXAMPLE_MODELS
10
from tests.utils import multi_gpu_test
11
from vllm import LLM
12
+from vllm.config import CUDAGraphMode
13
from vllm.engine.arg_utils import EngineArgs
14
from vllm.platforms import current_platform
15
from vllm.sampling_params import SamplingParams
@@ -210,6 +211,8 @@ def test_mamba_cache_cg_padding(
211
cudagraph_dispatcher.initialize_cudagraph_keys(
212
vllm_config.compilation_config.cudagraph_mode
213
)
214
+ if cudagraph_dispatcher.cudagraph_mode == CUDAGraphMode.NONE:
215
+ pytest.skip("CUDA/XPU graph is disabled.Please enable it to run this test. ")
216
while (
217
len(example_prompts)
218
== cudagraph_dispatcher.dispatch(len(example_prompts))[1].num_tokens
tests/models/language/pooling/test_colbert.py
+2
-2
@@ -11,7 +11,7 @@ from contextlib import contextmanager
11
import pytest
12
import torch
13
14
-from tests.utils import wait_for_rocm_memory_to_settle
14
+from tests.utils import wait_for_memory_to_settle
15
from vllm.distributed import cleanup_dist_env_and_memory
16
from vllm.entrypoints.pooling.scoring.utils import compute_maxsim_score
17
@@ -165,7 +165,7 @@ def _hf_colbert_model(model_name: str, hf_spec: dict, device: torch.device):
165
finally:
166
del hf_model, linear_weight
167
cleanup_dist_env_and_memory()
168
- wait_for_rocm_memory_to_settle()
168
+ wait_for_memory_to_settle()
169
170
171
def _assert_embeddings_close(vllm_outputs, hf_embeddings):
tests/models/multimodal/generation/test_voxtral_realtime.py
+4
-4
@@ -104,9 +104,9 @@ async def async_engine():
104
from vllm.platforms import current_platform
105
106
if current_platform.is_rocm():
107
- from tests.utils import wait_for_rocm_memory_to_settle
107
+ from tests.utils import wait_for_memory_to_settle
108
109
- wait_for_rocm_memory_to_settle(threshold_ratio=1.0 - gpu_memory_utilization)
109
+ wait_for_memory_to_settle(threshold_ratio=1.0 - gpu_memory_utilization)
110
111
engine_args = AsyncEngineArgs(**ENGINE_CONFIG)
112
llm = AsyncLLM.from_engine_args(engine_args)
@@ -122,9 +122,9 @@ async def async_engine():
122
from vllm.distributed import cleanup_dist_env_and_memory
123
124
cleanup_dist_env_and_memory()
125
- from tests.utils import wait_for_rocm_memory_to_settle
125
+ from tests.utils import wait_for_memory_to_settle
126
127
- wait_for_rocm_memory_to_settle(threshold_ratio=1.0 - gpu_memory_utilization)
127
+ wait_for_memory_to_settle(threshold_ratio=1.0 - gpu_memory_utilization)
128
129
130
def test_voxtral_realtime_forward(audio_assets, tokenizer, vllm_runner, monkeypatch):
tests/utils.py
+11
-4
@@ -1540,6 +1540,13 @@ def record_gpu_memory_usage_stats(
1540
mem_info = amdsmi_get_gpu_vram_usage(dev_handle)
1541
gb_used = mem_info["vram_used"] / 2**10
1542
gb_total = mem_info["vram_total"] / 2**10
1543
+ elif current_platform.is_xpu():
1544
+ # nvml/amdsmi are unavailable on XPU. Query device memory through
1545
+ # torch.accelerator.get_memory_info, which the XPU platform patches
1546
+ # to return (free, total) bytes via Level Zero.
1547
+ free_b, total_b = torch.accelerator.get_memory_info(device)
1548
+ gb_used = (total_b - free_b) / 2**30
1549
+ gb_total = total_b / 2**30
1550
else:
1551
dev_handle = get_nvml_device_handle(device)
1552
mem_info = nvmlDeviceGetMemoryInfo(dev_handle)
@@ -1680,19 +1687,19 @@ def wait_for_gpu_memory_to_clear(
1687
time.sleep(poll_interval_s)
1688
1689
1683
-def wait_for_rocm_memory_to_settle(
1690
+def wait_for_memory_to_settle(
1691
*,
1692
threshold_ratio: float | dict[int, float] | None = 0.1,
1693
timeout_s: float = 240,
1694
) -> None:
1688
- """Block until ROCm device VRAM usage drops below ``threshold_ratio``.
1695
+ """Block until ROCm or XPU device VRAM usage drops below ``threshold_ratio``.
1696
1690
- ROCm reclaims GPU memory more lazily than CUDA, so back-to-back model
1697
+ ROCm and XPU reclaims GPU memory more lazily than CUDA, so back-to-back model
1698
loads in a single test process can OOM the *next* engine/model startup
1699
even after ``cleanup_dist_env_and_memory``. This gives the driver time to
1700
actually release VRAM before the next allocation. No-op off ROCm.
1701
"""
1695
- if not current_platform.is_rocm():
1702
+ if not current_platform.is_rocm() and not current_platform.is_xpu():
1703
return
1704
1705
num_gpus = current_platform.device_count()
tests/v1/kv_connector/nixl_integration/run_accuracy_test.sh
+1
-1
@@ -112,7 +112,7 @@ wait_for_server() {
112
# Function to clean up previous instances
113
wait_for_gpu_memory_release() {
114
if [[ "$SMI_BIN" == *"rocm"* ]]; then
115
- PYTHONPATH="${GIT_ROOT}" python3 -c "from tests.utils import wait_for_rocm_memory_to_settle; wait_for_rocm_memory_to_settle()"
115
+ PYTHONPATH="${GIT_ROOT}" python3 -c "from tests.utils import wait_for_memory_to_settle; wait_for_memory_to_settle()"
116
fi
117
}
118