Add vLLM v0.18.1 source tree with KV transfer abort fix
third_party/vllm/ now tracked in git for direct patch management.
Based on vLLM v0.18.1 release with one patch applied:
vllm/v1/core/sched/scheduler.py:
Replace fatal assert with graceful skip when KV transfer callback
arrives for an already-aborted request during PD disaggregated serving.
Future vLLM modifications should be made directly in third_party/vllm/
and committed normally. The patches/ directory is kept as documentation
of what changed from upstream.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
23
third_party/vllm/tests/cuda/scripts/check_device_count_respects_env.py
vendored
Normal file
23
third_party/vllm/tests/cuda/scripts/check_device_count_respects_env.py
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
"""Check that device_count respects CUDA_VISIBLE_DEVICES after platform import."""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
for key in ["CUDA_VISIBLE_DEVICES", "HIP_VISIBLE_DEVICES", "ROCR_VISIBLE_DEVICES"]:
|
||||
os.environ.pop(key, None)
|
||||
|
||||
import torch # noqa: E402
|
||||
|
||||
from vllm.platforms import current_platform # noqa: F401, E402
|
||||
|
||||
os.environ["CUDA_VISIBLE_DEVICES"] = "0"
|
||||
count = torch.accelerator.device_count()
|
||||
|
||||
if count == 0:
|
||||
sys.exit(0) # Skip: no GPUs available
|
||||
|
||||
assert count == 1, f"device_count()={count}, expected 1"
|
||||
print("OK")
|
||||
20
third_party/vllm/tests/cuda/scripts/check_platform_no_cuda_init.py
vendored
Normal file
20
third_party/vllm/tests/cuda/scripts/check_platform_no_cuda_init.py
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
"""Check that vllm.platforms import does not initialize CUDA."""
|
||||
|
||||
import os
|
||||
|
||||
for key in ["CUDA_VISIBLE_DEVICES", "HIP_VISIBLE_DEVICES", "ROCR_VISIBLE_DEVICES"]:
|
||||
os.environ.pop(key, None)
|
||||
|
||||
import torch # noqa: E402
|
||||
|
||||
assert not torch.cuda.is_initialized(), "CUDA initialized before import"
|
||||
|
||||
from vllm.platforms import current_platform # noqa: E402
|
||||
|
||||
assert not torch.cuda.is_initialized(), (
|
||||
f"CUDA was initialized during vllm.platforms import on {current_platform}"
|
||||
)
|
||||
print("OK")
|
||||
187
third_party/vllm/tests/cuda/test_cuda_compatibility_path.py
vendored
Normal file
187
third_party/vllm/tests/cuda/test_cuda_compatibility_path.py
vendored
Normal file
@@ -0,0 +1,187 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
"""Tests for CUDA forward compatibility path logic in env_override.py.
|
||||
|
||||
Verifies the opt-in LD_LIBRARY_PATH manipulation for CUDA compat libs,
|
||||
including env var parsing, path detection, and deduplication.
|
||||
"""
|
||||
|
||||
import os
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
# Import the functions directly (they're module-level in env_override)
|
||||
# We must import them without triggering the module-level side effects,
|
||||
# so we import the functions by name after the module is already loaded.
|
||||
from vllm.env_override import (
|
||||
_get_torch_cuda_version,
|
||||
_maybe_set_cuda_compatibility_path,
|
||||
)
|
||||
|
||||
|
||||
class TestCudaCompatibilityEnvParsing:
|
||||
"""Test VLLM_ENABLE_CUDA_COMPATIBILITY env var parsing."""
|
||||
|
||||
def test_disabled_by_default(self, monkeypatch):
|
||||
"""Compat path is NOT set when env var is absent."""
|
||||
monkeypatch.delenv("VLLM_ENABLE_CUDA_COMPATIBILITY", raising=False)
|
||||
monkeypatch.delenv("LD_LIBRARY_PATH", raising=False)
|
||||
_maybe_set_cuda_compatibility_path()
|
||||
assert (
|
||||
"LD_LIBRARY_PATH" not in os.environ
|
||||
or os.environ.get("LD_LIBRARY_PATH", "") == ""
|
||||
)
|
||||
|
||||
@pytest.mark.parametrize("value", ["0", "false", "False", "no", ""])
|
||||
def test_disabled_values(self, monkeypatch, value):
|
||||
"""Various falsy values should not activate compat path."""
|
||||
monkeypatch.setenv("VLLM_ENABLE_CUDA_COMPATIBILITY", value)
|
||||
monkeypatch.delenv("LD_LIBRARY_PATH", raising=False)
|
||||
_maybe_set_cuda_compatibility_path()
|
||||
# LD_LIBRARY_PATH should not be set (or remain empty)
|
||||
ld_path = os.environ.get("LD_LIBRARY_PATH", "")
|
||||
assert "compat" not in ld_path
|
||||
|
||||
@pytest.mark.parametrize("value", ["1", "true", "True", " 1 ", " TRUE "])
|
||||
def test_enabled_values_with_valid_path(self, monkeypatch, tmp_path, value):
|
||||
"""Truthy values activate compat path when a valid path exists."""
|
||||
compat_dir = tmp_path / "compat"
|
||||
compat_dir.mkdir()
|
||||
monkeypatch.setenv("VLLM_ENABLE_CUDA_COMPATIBILITY", value)
|
||||
monkeypatch.setenv("VLLM_CUDA_COMPATIBILITY_PATH", str(compat_dir))
|
||||
monkeypatch.delenv("LD_LIBRARY_PATH", raising=False)
|
||||
_maybe_set_cuda_compatibility_path()
|
||||
ld_path = os.environ.get("LD_LIBRARY_PATH", "")
|
||||
assert str(compat_dir) in ld_path
|
||||
|
||||
|
||||
class TestCudaCompatibilityPathDetection:
|
||||
"""Test path detection: custom override, conda, default."""
|
||||
|
||||
def test_custom_path_override(self, monkeypatch, tmp_path):
|
||||
"""VLLM_CUDA_COMPATIBILITY_PATH takes highest priority."""
|
||||
custom_dir = tmp_path / "my-compat"
|
||||
custom_dir.mkdir()
|
||||
monkeypatch.setenv("VLLM_ENABLE_CUDA_COMPATIBILITY", "1")
|
||||
monkeypatch.setenv("VLLM_CUDA_COMPATIBILITY_PATH", str(custom_dir))
|
||||
monkeypatch.delenv("LD_LIBRARY_PATH", raising=False)
|
||||
_maybe_set_cuda_compatibility_path()
|
||||
ld_path = os.environ.get("LD_LIBRARY_PATH", "")
|
||||
assert ld_path.startswith(str(custom_dir))
|
||||
|
||||
def test_conda_prefix_fallback(self, monkeypatch, tmp_path):
|
||||
"""Falls back to $CONDA_PREFIX/cuda-compat if custom not set."""
|
||||
conda_dir = tmp_path / "conda-env"
|
||||
compat_dir = conda_dir / "cuda-compat"
|
||||
compat_dir.mkdir(parents=True)
|
||||
monkeypatch.setenv("VLLM_ENABLE_CUDA_COMPATIBILITY", "1")
|
||||
monkeypatch.delenv("VLLM_CUDA_COMPATIBILITY_PATH", raising=False)
|
||||
monkeypatch.setenv("CONDA_PREFIX", str(conda_dir))
|
||||
monkeypatch.delenv("LD_LIBRARY_PATH", raising=False)
|
||||
_maybe_set_cuda_compatibility_path()
|
||||
ld_path = os.environ.get("LD_LIBRARY_PATH", "")
|
||||
assert str(compat_dir) in ld_path
|
||||
|
||||
def test_no_valid_path_does_nothing(self, monkeypatch):
|
||||
"""When enabled but no valid path exists, LD_LIBRARY_PATH unchanged."""
|
||||
monkeypatch.setenv("VLLM_ENABLE_CUDA_COMPATIBILITY", "1")
|
||||
monkeypatch.setenv("VLLM_CUDA_COMPATIBILITY_PATH", "/nonexistent/path")
|
||||
monkeypatch.delenv("CONDA_PREFIX", raising=False)
|
||||
monkeypatch.delenv("LD_LIBRARY_PATH", raising=False)
|
||||
with patch("vllm.env_override._get_torch_cuda_version", return_value=None):
|
||||
_maybe_set_cuda_compatibility_path()
|
||||
assert os.environ.get("LD_LIBRARY_PATH", "") == ""
|
||||
|
||||
def test_default_cuda_path_fallback(self, monkeypatch, tmp_path):
|
||||
"""Falls back to /usr/local/cuda-{ver}/compat via torch version."""
|
||||
fake_cuda = tmp_path / "cuda-12.8" / "compat"
|
||||
fake_cuda.mkdir(parents=True)
|
||||
monkeypatch.setenv("VLLM_ENABLE_CUDA_COMPATIBILITY", "1")
|
||||
monkeypatch.delenv("VLLM_CUDA_COMPATIBILITY_PATH", raising=False)
|
||||
monkeypatch.delenv("CONDA_PREFIX", raising=False)
|
||||
monkeypatch.delenv("LD_LIBRARY_PATH", raising=False)
|
||||
with (
|
||||
patch("vllm.env_override._get_torch_cuda_version", return_value="12.8"),
|
||||
patch(
|
||||
"vllm.env_override.os.path.isdir",
|
||||
side_effect=lambda p: p == "/usr/local/cuda-12.8/compat"
|
||||
or os.path.isdir(p),
|
||||
),
|
||||
):
|
||||
_maybe_set_cuda_compatibility_path()
|
||||
ld_path = os.environ.get("LD_LIBRARY_PATH", "")
|
||||
assert "/usr/local/cuda-12.8/compat" in ld_path
|
||||
|
||||
|
||||
class TestCudaCompatibilityLdPathManipulation:
|
||||
"""Test LD_LIBRARY_PATH prepend and deduplication logic."""
|
||||
|
||||
def test_prepends_to_empty_ld_path(self, monkeypatch, tmp_path):
|
||||
"""Compat path is set when LD_LIBRARY_PATH is empty."""
|
||||
compat_dir = tmp_path / "compat"
|
||||
compat_dir.mkdir()
|
||||
monkeypatch.setenv("VLLM_ENABLE_CUDA_COMPATIBILITY", "1")
|
||||
monkeypatch.setenv("VLLM_CUDA_COMPATIBILITY_PATH", str(compat_dir))
|
||||
monkeypatch.delenv("LD_LIBRARY_PATH", raising=False)
|
||||
_maybe_set_cuda_compatibility_path()
|
||||
assert os.environ["LD_LIBRARY_PATH"] == str(compat_dir)
|
||||
|
||||
def test_prepends_to_existing_ld_path(self, monkeypatch, tmp_path):
|
||||
"""Compat path is prepended before existing entries."""
|
||||
compat_dir = tmp_path / "compat"
|
||||
compat_dir.mkdir()
|
||||
monkeypatch.setenv("VLLM_ENABLE_CUDA_COMPATIBILITY", "1")
|
||||
monkeypatch.setenv("VLLM_CUDA_COMPATIBILITY_PATH", str(compat_dir))
|
||||
monkeypatch.setenv("LD_LIBRARY_PATH", "/usr/lib:/other/lib")
|
||||
_maybe_set_cuda_compatibility_path()
|
||||
ld_path = os.environ["LD_LIBRARY_PATH"]
|
||||
parts = ld_path.split(os.pathsep)
|
||||
assert parts[0] == str(compat_dir)
|
||||
assert "/usr/lib" in parts
|
||||
assert "/other/lib" in parts
|
||||
|
||||
def test_deduplicates_existing_compat_path(self, monkeypatch, tmp_path):
|
||||
"""If compat path already in LD_LIBRARY_PATH, move to front."""
|
||||
compat_dir = tmp_path / "compat"
|
||||
compat_dir.mkdir()
|
||||
monkeypatch.setenv("VLLM_ENABLE_CUDA_COMPATIBILITY", "1")
|
||||
monkeypatch.setenv("VLLM_CUDA_COMPATIBILITY_PATH", str(compat_dir))
|
||||
monkeypatch.setenv(
|
||||
"LD_LIBRARY_PATH",
|
||||
f"/usr/lib:{compat_dir}:/other/lib",
|
||||
)
|
||||
_maybe_set_cuda_compatibility_path()
|
||||
ld_path = os.environ["LD_LIBRARY_PATH"]
|
||||
parts = ld_path.split(os.pathsep)
|
||||
assert parts[0] == str(compat_dir)
|
||||
assert parts.count(str(compat_dir)) == 1
|
||||
|
||||
def test_already_at_front_is_noop(self, monkeypatch, tmp_path):
|
||||
"""If compat path is already first, don't modify LD_LIBRARY_PATH."""
|
||||
compat_dir = tmp_path / "compat"
|
||||
compat_dir.mkdir()
|
||||
original = f"{compat_dir}:/usr/lib"
|
||||
monkeypatch.setenv("VLLM_ENABLE_CUDA_COMPATIBILITY", "1")
|
||||
monkeypatch.setenv("VLLM_CUDA_COMPATIBILITY_PATH", str(compat_dir))
|
||||
monkeypatch.setenv("LD_LIBRARY_PATH", original)
|
||||
_maybe_set_cuda_compatibility_path()
|
||||
assert os.environ["LD_LIBRARY_PATH"] == original
|
||||
|
||||
|
||||
class TestGetTorchCudaVersion:
|
||||
"""Test _get_torch_cuda_version() helper."""
|
||||
|
||||
def test_returns_string_when_torch_available(self):
|
||||
"""Should return a CUDA version string like '12.8'."""
|
||||
version = _get_torch_cuda_version()
|
||||
# torch is installed in vllm's environment
|
||||
assert version is None or isinstance(version, str)
|
||||
|
||||
def test_returns_none_when_torch_missing(self):
|
||||
"""Should return None when torch is not importable."""
|
||||
with patch(
|
||||
"vllm.env_override.importlib.util.find_spec",
|
||||
return_value=None,
|
||||
):
|
||||
assert _get_torch_cuda_version() is None
|
||||
81
third_party/vllm/tests/cuda/test_cuda_context.py
vendored
Normal file
81
third_party/vllm/tests/cuda/test_cuda_context.py
vendored
Normal file
@@ -0,0 +1,81 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
|
||||
import ctypes
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
||||
import pytest
|
||||
import torch
|
||||
|
||||
from vllm.platforms import current_platform
|
||||
|
||||
|
||||
def check_cuda_context():
|
||||
"""Check CUDA driver context status"""
|
||||
try:
|
||||
cuda = ctypes.CDLL("libcuda.so")
|
||||
device = ctypes.c_int()
|
||||
result = cuda.cuCtxGetDevice(ctypes.byref(device))
|
||||
return (True, device.value) if result == 0 else (False, None)
|
||||
except Exception:
|
||||
return False, None
|
||||
|
||||
|
||||
def run_cuda_test_in_thread(device_input, expected_device_id):
|
||||
"""Run CUDA context test in separate thread for isolation"""
|
||||
try:
|
||||
# New thread should have no CUDA context initially
|
||||
valid_before, device_before = check_cuda_context()
|
||||
if valid_before:
|
||||
return (
|
||||
False,
|
||||
"CUDA context should not exist in new thread, "
|
||||
f"got device {device_before}",
|
||||
)
|
||||
|
||||
# Test setting CUDA context
|
||||
current_platform.set_device(device_input)
|
||||
|
||||
# Verify context is created correctly
|
||||
valid_after, device_id = check_cuda_context()
|
||||
if not valid_after:
|
||||
return False, "CUDA context should be valid after set_cuda_context"
|
||||
if device_id != expected_device_id:
|
||||
return False, f"Expected device {expected_device_id}, got {device_id}"
|
||||
|
||||
return True, "Success"
|
||||
except Exception as e:
|
||||
return False, f"Exception in thread: {str(e)}"
|
||||
|
||||
|
||||
class TestSetCudaContext:
|
||||
"""Test suite for the set_cuda_context function."""
|
||||
|
||||
@pytest.mark.skipif(not current_platform.is_cuda(), reason="CUDA not available")
|
||||
@pytest.mark.parametrize(
|
||||
argnames="device_input,expected_device_id",
|
||||
argvalues=[
|
||||
(0, 0),
|
||||
(torch.device("cuda:0"), 0),
|
||||
("cuda:0", 0),
|
||||
],
|
||||
ids=["int", "torch_device", "string"],
|
||||
)
|
||||
def test_set_cuda_context_parametrized(self, device_input, expected_device_id):
|
||||
"""Test setting CUDA context in isolated threads."""
|
||||
with ThreadPoolExecutor(max_workers=1) as executor:
|
||||
future = executor.submit(
|
||||
run_cuda_test_in_thread, device_input, expected_device_id
|
||||
)
|
||||
success, message = future.result(timeout=30)
|
||||
assert success, message
|
||||
|
||||
@pytest.mark.skipif(not current_platform.is_cuda(), reason="CUDA not available")
|
||||
def test_set_cuda_context_invalid_device_type(self):
|
||||
"""Test error handling for invalid device type."""
|
||||
with pytest.raises(ValueError, match="Expected a cuda device"):
|
||||
current_platform.set_device(torch.device("cpu"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v"])
|
||||
48
third_party/vllm/tests/cuda/test_platform_no_cuda_init.py
vendored
Normal file
48
third_party/vllm/tests/cuda/test_platform_no_cuda_init.py
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
|
||||
"""
|
||||
Test that platform imports do not prematurely initialize CUDA.
|
||||
|
||||
This is critical for Ray-based multi-GPU setups where workers need to
|
||||
set CUDA_VISIBLE_DEVICES after importing vLLM but before CUDA is initialized.
|
||||
If CUDA is initialized during import, device_count() gets locked and ignores
|
||||
subsequent env var changes.
|
||||
"""
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
SCRIPTS_DIR = Path(__file__).parent / "scripts"
|
||||
|
||||
|
||||
def run_script(script_name: str) -> subprocess.CompletedProcess:
|
||||
"""Run a test script in a subprocess with clean CUDA state."""
|
||||
script_path = SCRIPTS_DIR / script_name
|
||||
return subprocess.run(
|
||||
[sys.executable, str(script_path)],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
|
||||
|
||||
def test_platform_import_does_not_init_cuda():
|
||||
"""Test that importing vllm.platforms does not initialize CUDA."""
|
||||
result = run_script("check_platform_no_cuda_init.py")
|
||||
if result.returncode != 0:
|
||||
pytest.fail(f"Platform import initialized CUDA:\n{result.stderr}")
|
||||
|
||||
|
||||
def test_device_count_respects_env_after_platform_import():
|
||||
"""Test that device_count respects CUDA_VISIBLE_DEVICES after import."""
|
||||
result = run_script("check_device_count_respects_env.py")
|
||||
if result.returncode != 0:
|
||||
pytest.fail(
|
||||
f"device_count does not respect env var after import:\n{result.stderr}"
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
pytest.main([__file__, "-v"])
|
||||
Reference in New Issue
Block a user