Skip to content

Commit a90c97c

Browse files
committed
[None][test] Organize multi-GPU tests into gpu2/gpu4 classes with class-scoped sessions
Group test_llm_multi_gpu_pytorch.py into TestLlmMultiGpu2gpu (@gpu2) and TestLlmMultiGpu4gpu (@gpu4), sharing a small _MultiGpuLlmTests base whose class-scoped mpi_session/mpi_kwargs/shared_llm fixtures build one MpiPoolSession of self.n_gpus workers. The session is created lazily and torn down at class end, so the 2-GPU and 4-GPU pools no longer coexist (as they did with the previous module-scoped fixtures). Update the two explicit nodeid references for test_phi3_lora_fused_modules_output_on_tp2_identical_to_tp1 (l0_dgx_h100.yml, waives.txt) to include the class; -m gpu2/gpu4 and -k filters are unaffected. Signed-off-by: qgai <qgai@nvidia.com>
1 parent 3ea78e0 commit a90c97c

3 files changed

Lines changed: 168 additions & 185 deletions

File tree

tests/integration/test_lists/test-db/l0_dgx_h100.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ l0_dgx_h100:
1515
auto_trigger: others
1616
orchestrator: mpi
1717
tests:
18-
- unittest/llmapi/test_llm_multi_gpu_pytorch.py::test_phi3_lora_fused_modules_output_on_tp2_identical_to_tp1
18+
- unittest/llmapi/test_llm_multi_gpu_pytorch.py::TestLlmMultiGpu2gpu::test_phi3_lora_fused_modules_output_on_tp2_identical_to_tp1
1919
- unittest/llmapi/test_llm_multi_gpu_pytorch.py -m "gpu2" -k "not test_phi3_lora_fused_modules_output_on_tp2_identical_to_tp1"
2020
- unittest/llmapi/test_additional_model_outputs.py -m "gpu2"
2121
- unittest/_torch/multi_gpu -m "not post_merge" TIMEOUT (90)

tests/integration/test_lists/waives.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ unittest/executor/test_rpc.py::TestRpcCorrectness::test_incremental_task_async S
488488
unittest/executor/test_rpc_proxy.py SKIP (https://nvbugs/5605741)
489489
unittest/executor/test_rpc_worker.py SKIP (https://nvbugs/5605741)
490490
unittest/llmapi/test_llm_multi_gpu.py -m "gpu4 and part0" SKIP (https://nvbugs/5348958)
491-
unittest/llmapi/test_llm_multi_gpu_pytorch.py::test_phi3_lora_fused_modules_output_on_tp2_identical_to_tp1 SKIP (https://nvbugs/6109745)
491+
unittest/llmapi/test_llm_multi_gpu_pytorch.py::TestLlmMultiGpu2gpu::test_phi3_lora_fused_modules_output_on_tp2_identical_to_tp1 SKIP (https://nvbugs/6109745)
492492
unittest/llmapi/test_llm_pytorch.py::test_gqa_nemo_lora[None] SKIP (https://nvbugs/6162504)
493493
unittest/llmapi/test_llm_pytorch.py::test_gqa_nemo_lora[cuda_graph_config0] SKIP (https://nvbugs/6162504)
494494
unittest/llmapi/test_memory_profiling.py::test_profile_kvcache SKIP (https://nvbugs/5580781)

tests/unittest/llmapi/test_llm_multi_gpu_pytorch.py

Lines changed: 166 additions & 183 deletions
Original file line numberDiff line numberDiff line change
@@ -27,110 +27,6 @@
2727
global_kv_cache_config = KvCacheConfig(free_gpu_memory_fraction=0.4)
2828

2929

30-
@pytest.fixture(scope="module")
31-
def shared_mpi_session_2gpu():
32-
yield from _shared_mpi_session(2)
33-
34-
35-
@pytest.fixture(scope="module")
36-
def shared_mpi_session_4gpu():
37-
yield from _shared_mpi_session(4)
38-
39-
40-
@pytest.fixture(scope="module")
41-
def shared_llm_2gpu(shared_mpi_session_2gpu):
42-
# Factory for tests that construct the LLM directly (see RPC tests below).
43-
return _make_shared_llm(shared_mpi_session_2gpu)
44-
45-
46-
@pytest.fixture(scope="module")
47-
def mpi_kwargs_2gpu(shared_mpi_session_2gpu):
48-
# Ready-to-spread LLM kwargs that inject the shared 2-GPU session (or {} when
49-
# MPI is disabled). Harness-based tests just spread this; they never touch the
50-
# raw session object.
51-
return _mpi_session_kwargs(shared_mpi_session_2gpu)
52-
53-
54-
@pytest.fixture(scope="module")
55-
def mpi_kwargs_4gpu(shared_mpi_session_4gpu):
56-
return _mpi_session_kwargs(shared_mpi_session_4gpu)
57-
58-
59-
@pytest.mark.gpu2
60-
def test_llm_capture_request_error(mpi_kwargs_2gpu):
61-
_test_llm_capture_request_error(pytorch_backend=True,
62-
tp_size=2,
63-
**mpi_kwargs_2gpu)
64-
65-
66-
@pytest.mark.gpu4
67-
def test_tinyllama_logits_processor_tp2pp2(mpi_kwargs_4gpu):
68-
tinyllama_logits_processor_test_harness(backend="pytorch",
69-
tensor_parallel_size=2,
70-
pipeline_parallel_size=2,
71-
**mpi_kwargs_4gpu)
72-
73-
74-
@pytest.mark.gpu2
75-
@pytest.mark.part0
76-
@pytest.mark.parametrize("tp_size, pp_size", [(1, 2), (2, 1)])
77-
def test_tinyllama_logits_processor_2gpu(tp_size: int, pp_size: int,
78-
mpi_kwargs_2gpu):
79-
tinyllama_logits_processor_test_harness(backend="pytorch",
80-
tensor_parallel_size=tp_size,
81-
pipeline_parallel_size=pp_size,
82-
**mpi_kwargs_2gpu)
83-
84-
85-
@pytest.mark.gpu2
86-
def test_llama_7b_lora_tp2(mpi_kwargs_2gpu):
87-
llama_7b_lora_from_dir_test_harness(tensor_parallel_size=2,
88-
kv_cache_config=global_kv_cache_config,
89-
**mpi_kwargs_2gpu)
90-
91-
92-
@pytest.mark.gpu4
93-
@skip_ray # https://nvbugs/5682551
94-
@test_lora_with_and_without_cuda_graph
95-
def test_llama_7b_multi_lora_tp4(cuda_graph_config, mpi_kwargs_4gpu):
96-
# For LoRA checkpoints without finetuned embedding and lm_head, we can either:
97-
# (1) specify lora_target_modules, or
98-
# (2) provide a lora_dir to infer the lora_target_modules.
99-
lora_config = LoraConfig(lora_target_modules=['attn_q', 'attn_k', 'attn_v'],
100-
max_lora_rank=8,
101-
max_loras=1,
102-
max_cpu_loras=8)
103-
check_llama_7b_multi_lora_from_request_test_harness(
104-
LLM,
105-
lora_config=lora_config,
106-
tensor_parallel_size=4,
107-
kv_cache_config=global_kv_cache_config,
108-
cuda_graph_config=cuda_graph_config,
109-
**mpi_kwargs_4gpu)
110-
111-
112-
@skip_ray # https://nvbugs/5727075
113-
@pytest.mark.gpu2
114-
@test_lora_with_and_without_cuda_graph
115-
def test_phi3_lora_fused_modules_output_on_tp2_identical_to_tp1(
116-
cuda_graph_config) -> None:
117-
check_phi3_lora_fused_modules_output_tp2_identical_to_tp1(
118-
LLM, cuda_graph_config=cuda_graph_config)
119-
120-
121-
@skip_ray
122-
@pytest.mark.gpu2
123-
def test_llm_rpc_tp2(shared_llm_2gpu):
124-
_run_llm_rpc_tp2(shared_llm_2gpu)
125-
126-
127-
@skip_ray
128-
@pytest.mark.gpu2
129-
@pytest.mark.asyncio
130-
async def test_llm_rpc_streaming_tp2(shared_llm_2gpu):
131-
await _run_llm_rpc_streaming_tp2(shared_llm_2gpu)
132-
133-
13430
def _run_llm_rpc_tp2(make_llm=LLM):
13531
with make_llm(model=llama_model_path,
13632
kv_cache_config=KvCacheConfig(free_gpu_memory_fraction=0.4),
@@ -160,91 +56,178 @@ async def _run_llm_rpc_streaming_tp2(make_llm=LLM):
16056
print(f"get result: {output}")
16157

16258

163-
@skip_ray
164-
@pytest.mark.gpu2
165-
@pytest.mark.parametrize(
166-
"prompt_logprobs, logprobs, return_context_logits, return_generation_logits",
167-
[
168-
(None, 1, False,
169-
False), # generation logprobs only (top-1, PyTorch limit)
170-
])
171-
def test_llm_return_logprobs_streaming_tp2(prompt_logprobs, logprobs,
172-
return_context_logits,
173-
return_generation_logits,
174-
mpi_kwargs_2gpu):
175-
llm_return_logprobs_test_harness(prompt_logprobs,
176-
logprobs,
177-
return_context_logits,
178-
return_generation_logits,
179-
streaming=True,
180-
backend="pytorch",
181-
tp_size=2,
182-
**mpi_kwargs_2gpu)
183-
184-
185-
@skip_ray
186-
@pytest.mark.gpu2
187-
@pytest.mark.parametrize(
188-
"return_context_logits, enable_chunked_prefill, enable_iter_req_stats",
189-
[
190-
(False, False, True),
191-
(False, True, True),
192-
],
193-
)
194-
def test_llm_get_stats_pp2(return_context_logits, enable_chunked_prefill,
195-
enable_iter_req_stats, mpi_kwargs_2gpu):
196-
llm_get_stats_test_harness(
197-
tp_size=1,
198-
pp_size=2,
199-
return_context_logits=return_context_logits,
200-
pytorch_backend=True,
201-
enable_chunked_prefill=enable_chunked_prefill,
202-
enable_iter_req_stats=enable_iter_req_stats,
203-
**mpi_kwargs_2gpu,
204-
)
59+
class _MultiGpuLlmTests:
60+
"""Base for the multi-GPU LLM API test classes.
20561
62+
Subclasses set ``n_gpus``; the class-scoped fixtures below build one shared
63+
MpiPoolSession (of that many workers) reused across the subclass's tests and
64+
torn down when the subclass finishes -- so the 2-GPU and 4-GPU pools never
65+
coexist. Fixtures are lazy, so tests that opt out (e.g. constructing a bare
66+
``LLM``) simply don't request them and pay no session cost.
67+
"""
68+
n_gpus: int
20669

207-
@skip_ray
208-
@pytest.mark.gpu4
209-
@pytest.mark.parametrize(
210-
"return_context_logits, enable_chunked_prefill, enable_iter_req_stats",
211-
[
212-
(False, False, True),
213-
(False, True, True),
214-
],
215-
)
216-
def test_llm_get_stats_pp4(return_context_logits, enable_chunked_prefill,
217-
enable_iter_req_stats, mpi_kwargs_4gpu):
218-
llm_get_stats_test_harness(
219-
tp_size=1,
220-
pp_size=4,
221-
return_context_logits=return_context_logits,
222-
pytorch_backend=True,
223-
enable_chunked_prefill=enable_chunked_prefill,
224-
enable_iter_req_stats=enable_iter_req_stats,
225-
**mpi_kwargs_4gpu,
226-
)
70+
@pytest.fixture(scope="class")
71+
def mpi_session(self):
72+
yield from _shared_mpi_session(self.n_gpus)
22773

74+
@pytest.fixture(scope="class")
75+
def mpi_kwargs(self, mpi_session):
76+
return _mpi_session_kwargs(mpi_session)
22877

229-
@skip_ray
230-
@pytest.mark.gpu2
231-
def test_llm_get_stats_tp2(mpi_kwargs_2gpu):
232-
llm_get_stats_test_harness(tp_size=2,
233-
pytorch_backend=True,
234-
**mpi_kwargs_2gpu)
78+
@pytest.fixture(scope="class")
79+
def shared_llm(self, mpi_session):
80+
return _make_shared_llm(mpi_session)
23581

23682

237-
@skip_ray
23883
@pytest.mark.gpu2
239-
def test_llm_get_stats_async_tp2(mpi_kwargs_2gpu):
240-
llm_get_stats_async_test_harness(tp_size=2,
241-
pytorch_backend=True,
242-
**mpi_kwargs_2gpu)
84+
class TestLlmMultiGpu2gpu(_MultiGpuLlmTests):
85+
"""2-GPU multi-GPU LLM API tests (shared session from _MultiGpuLlmTests)."""
86+
n_gpus = 2
87+
88+
def test_llm_capture_request_error(self, mpi_kwargs):
89+
_test_llm_capture_request_error(pytorch_backend=True,
90+
tp_size=2,
91+
**mpi_kwargs)
92+
93+
@pytest.mark.part0
94+
@pytest.mark.parametrize("tp_size, pp_size", [(1, 2), (2, 1)])
95+
def test_tinyllama_logits_processor_2gpu(self, tp_size, pp_size,
96+
mpi_kwargs):
97+
tinyllama_logits_processor_test_harness(backend="pytorch",
98+
tensor_parallel_size=tp_size,
99+
pipeline_parallel_size=pp_size,
100+
**mpi_kwargs)
101+
102+
def test_llama_7b_lora_tp2(self, mpi_kwargs):
103+
llama_7b_lora_from_dir_test_harness(
104+
tensor_parallel_size=2,
105+
kv_cache_config=global_kv_cache_config,
106+
**mpi_kwargs)
107+
108+
@skip_ray # https://nvbugs/5727075
109+
@test_lora_with_and_without_cuda_graph
110+
def test_phi3_lora_fused_modules_output_on_tp2_identical_to_tp1(
111+
self, cuda_graph_config) -> None:
112+
check_phi3_lora_fused_modules_output_tp2_identical_to_tp1(
113+
LLM, cuda_graph_config=cuda_graph_config)
114+
115+
@skip_ray
116+
def test_llm_rpc_tp2(self, shared_llm):
117+
_run_llm_rpc_tp2(shared_llm)
118+
119+
@skip_ray
120+
@pytest.mark.asyncio
121+
async def test_llm_rpc_streaming_tp2(self, shared_llm):
122+
await _run_llm_rpc_streaming_tp2(shared_llm)
123+
124+
@skip_ray
125+
@pytest.mark.parametrize(
126+
"prompt_logprobs, logprobs, return_context_logits, return_generation_logits",
127+
[
128+
(None, 1, False,
129+
False), # generation logprobs only (top-1, PyTorch limit)
130+
])
131+
def test_llm_return_logprobs_streaming_tp2(self, prompt_logprobs, logprobs,
132+
return_context_logits,
133+
return_generation_logits,
134+
mpi_kwargs):
135+
llm_return_logprobs_test_harness(prompt_logprobs,
136+
logprobs,
137+
return_context_logits,
138+
return_generation_logits,
139+
streaming=True,
140+
backend="pytorch",
141+
tp_size=2,
142+
**mpi_kwargs)
143+
144+
@skip_ray
145+
@pytest.mark.parametrize(
146+
"return_context_logits, enable_chunked_prefill, enable_iter_req_stats",
147+
[
148+
(False, False, True),
149+
(False, True, True),
150+
],
151+
)
152+
def test_llm_get_stats_pp2(self, return_context_logits,
153+
enable_chunked_prefill, enable_iter_req_stats,
154+
mpi_kwargs):
155+
llm_get_stats_test_harness(
156+
tp_size=1,
157+
pp_size=2,
158+
return_context_logits=return_context_logits,
159+
pytorch_backend=True,
160+
enable_chunked_prefill=enable_chunked_prefill,
161+
enable_iter_req_stats=enable_iter_req_stats,
162+
**mpi_kwargs,
163+
)
164+
165+
@skip_ray
166+
def test_llm_get_stats_tp2(self, mpi_kwargs):
167+
llm_get_stats_test_harness(tp_size=2,
168+
pytorch_backend=True,
169+
**mpi_kwargs)
170+
171+
@skip_ray
172+
def test_llm_get_stats_async_tp2(self, mpi_kwargs):
173+
llm_get_stats_async_test_harness(tp_size=2,
174+
pytorch_backend=True,
175+
**mpi_kwargs)
176+
177+
@skip_ray
178+
def test_llm_get_stats_async_pp2(self, mpi_kwargs):
179+
llm_get_stats_async_test_harness(pp_size=2,
180+
pytorch_backend=True,
181+
**mpi_kwargs)
243182

244183

245-
@skip_ray
246-
@pytest.mark.gpu2
247-
def test_llm_get_stats_async_pp2(mpi_kwargs_2gpu):
248-
llm_get_stats_async_test_harness(pp_size=2,
249-
pytorch_backend=True,
250-
**mpi_kwargs_2gpu)
184+
@pytest.mark.gpu4
185+
class TestLlmMultiGpu4gpu(_MultiGpuLlmTests):
186+
"""4-GPU multi-GPU LLM API tests (shared session from _MultiGpuLlmTests)."""
187+
n_gpus = 4
188+
189+
def test_tinyllama_logits_processor_tp2pp2(self, mpi_kwargs):
190+
tinyllama_logits_processor_test_harness(backend="pytorch",
191+
tensor_parallel_size=2,
192+
pipeline_parallel_size=2,
193+
**mpi_kwargs)
194+
195+
@skip_ray # https://nvbugs/5682551
196+
@test_lora_with_and_without_cuda_graph
197+
def test_llama_7b_multi_lora_tp4(self, cuda_graph_config, mpi_kwargs):
198+
# For LoRA checkpoints without finetuned embedding and lm_head, we can
199+
# either: (1) specify lora_target_modules, or (2) provide a lora_dir to
200+
# infer the lora_target_modules.
201+
lora_config = LoraConfig(
202+
lora_target_modules=['attn_q', 'attn_k', 'attn_v'],
203+
max_lora_rank=8,
204+
max_loras=1,
205+
max_cpu_loras=8)
206+
check_llama_7b_multi_lora_from_request_test_harness(
207+
LLM,
208+
lora_config=lora_config,
209+
tensor_parallel_size=4,
210+
kv_cache_config=global_kv_cache_config,
211+
cuda_graph_config=cuda_graph_config,
212+
**mpi_kwargs)
213+
214+
@skip_ray
215+
@pytest.mark.parametrize(
216+
"return_context_logits, enable_chunked_prefill, enable_iter_req_stats",
217+
[
218+
(False, False, True),
219+
(False, True, True),
220+
],
221+
)
222+
def test_llm_get_stats_pp4(self, return_context_logits,
223+
enable_chunked_prefill, enable_iter_req_stats,
224+
mpi_kwargs):
225+
llm_get_stats_test_harness(
226+
tp_size=1,
227+
pp_size=4,
228+
return_context_logits=return_context_logits,
229+
pytorch_backend=True,
230+
enable_chunked_prefill=enable_chunked_prefill,
231+
enable_iter_req_stats=enable_iter_req_stats,
232+
**mpi_kwargs,
233+
)

0 commit comments

Comments
 (0)