main
py 156 lines 5.36 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3 """Test that we handle a startup Error and shutdown."""
4
5 import pytest
6
7 from tests.conftest import VllmRunner
8 from tests.utils import create_new_process_for_each_test, wait_for_gpu_memory_to_clear
9 from tests.v1.shutdown.utils import (
10 SHUTDOWN_TEST_THRESHOLD_BYTES,
11 SHUTDOWN_TEST_TIMEOUT_SEC,
12 )
13 from vllm import LLM, SamplingParams
14 from vllm.config import KernelConfig
15 from vllm.engine.arg_utils import AsyncEngineArgs
16 from vllm.platforms import current_platform
17 from vllm.sampling_params import RequestOutputKind
18 from vllm.v1.engine.async_llm import AsyncLLM
19
20 MODELS = ["hmellor/tiny-random-LlamaForCausalLM"]
21
22
23 @pytest.mark.asyncio
24 @pytest.mark.timeout(SHUTDOWN_TEST_TIMEOUT_SEC)
25 @pytest.mark.parametrize("model", MODELS)
26 @pytest.mark.parametrize("tensor_parallel_size", [2, 1])
27 @pytest.mark.parametrize("send_one_request", [False, True])
28 async def test_async_llm_delete(
29 model: str, tensor_parallel_size: int, send_one_request: bool
30 ) -> None:
31 """Test that AsyncLLM frees GPU memory upon deletion.
32 AsyncLLM always uses an MP client.
33
34 Args:
35 model: model under test
36 tensor_parallel_size: degree of tensor parallelism
37 send_one_request: send one request to engine before deleting
38
39 """
40 if current_platform.device_count() < tensor_parallel_size:
41 pytest.skip(reason="Not enough CUDA devices")
42
43 engine_args = AsyncEngineArgs(
44 model=model,
45 enforce_eager=True,
46 tensor_parallel_size=tensor_parallel_size,
47 kernel_config=KernelConfig(enable_jit_warmup=False),
48 )
49
50 # Instantiate AsyncLLM; make request to complete any deferred
51 # initialization; then delete instance
52 async_llm = AsyncLLM.from_engine_args(engine_args)
53 if send_one_request:
54 async for _ in async_llm.generate(
55 "Hello my name is",
56 request_id="abc",
57 sampling_params=SamplingParams(
58 max_tokens=1, output_kind=RequestOutputKind.DELTA
59 ),
60 ):
61 pass
62 del async_llm
63
64 # Confirm all the processes are cleaned up.
65 wait_for_gpu_memory_to_clear(
66 devices=list(range(tensor_parallel_size)),
67 threshold_bytes=SHUTDOWN_TEST_THRESHOLD_BYTES,
68 )
69
70
71 @pytest.mark.timeout(SHUTDOWN_TEST_TIMEOUT_SEC)
72 @pytest.mark.parametrize("model", MODELS)
73 @pytest.mark.parametrize("tensor_parallel_size", [2, 1])
74 @pytest.mark.parametrize("enable_multiprocessing", [True])
75 @pytest.mark.parametrize("send_one_request", [False, True])
76 def test_llm_delete(
77 monkeypatch,
78 model: str,
79 tensor_parallel_size: int,
80 enable_multiprocessing: bool,
81 send_one_request: bool,
82 ) -> None:
83 """Test that LLM frees GPU memory upon deletion.
84 TODO(andy) - LLM without multiprocessing.
85
86 Args:
87 model: model under test
88 tensor_parallel_size: degree of tensor parallelism
89 enable_multiprocessing: enable workers in separate process(es)
90 send_one_request: send one request to engine before deleting
91
92 """
93 if current_platform.device_count() < tensor_parallel_size:
94 pytest.skip(reason="Not enough CUDA devices")
95
96 with monkeypatch.context() as m:
97 MP_VALUE = "1" if enable_multiprocessing else "0"
98 m.setenv("VLLM_ENABLE_V1_MULTIPROCESSING", MP_VALUE)
99
100 # Instantiate LLM; make request to complete any deferred
101 # initialization; then delete instance
102 llm = LLM(
103 model=model,
104 enforce_eager=True,
105 tensor_parallel_size=tensor_parallel_size,
106 kernel_config=KernelConfig(enable_jit_warmup=False),
107 )
108 if send_one_request:
109 llm.generate(
110 "Hello my name is", sampling_params=SamplingParams(max_tokens=1)
111 )
112 del llm
113
114 # Confirm all the processes are cleaned up.
115 wait_for_gpu_memory_to_clear(
116 devices=list(range(tensor_parallel_size)),
117 threshold_bytes=SHUTDOWN_TEST_THRESHOLD_BYTES,
118 )
119
120
121 @create_new_process_for_each_test("fork" if current_platform.is_cuda() else "spawn")
122 @pytest.mark.timeout(SHUTDOWN_TEST_TIMEOUT_SEC)
123 @pytest.mark.parametrize("model", MODELS)
124 @pytest.mark.parametrize("send_one_request", [False, True])
125 def test_llm_delete_inprocess(
126 monkeypatch,
127 model: str,
128 send_one_request: bool,
129 ) -> None:
130 """Test that VllmRunner frees GPU memory in in-process (no MP) mode."""
131 with monkeypatch.context() as m:
132 m.setenv("VLLM_ENABLE_V1_MULTIPROCESSING", "0")
133
134 with VllmRunner(
135 model,
136 kernel_config=KernelConfig(enable_jit_warmup=False),
137 ) as vllm_model:
138 if send_one_request:
139 vllm_model.generate(
140 ["Hello my name is"],
141 SamplingParams(max_tokens=1),
142 )
143
144 wait_for_gpu_memory_to_clear(
145 devices=[0],
146 threshold_bytes=SHUTDOWN_TEST_THRESHOLD_BYTES,
147 # Activate the helper's ROCm idle-runtime floor. VllmRunner already
148 # performed the stable-memory wait during context exit.
149 threshold_ratio=0.01 if current_platform.is_rocm() else None,
150 # Fail in the child before the outer pytest timeout expires.
151 timeout_s=(
152 SHUTDOWN_TEST_TIMEOUT_SEC // 2
153 if current_platform.is_rocm()
154 else SHUTDOWN_TEST_TIMEOUT_SEC
155 ),
156 )