main
py 192 lines 7.05 KB
Raw
1 # SPDX-License-Identifier: Apache-2.0
2 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4 import pytest
5
6 from vllm.compilation.passes.fusion.sequence_parallelism import (
7 SP_MIN_HIDDEN_SIZE,
8 SP_MIN_PER_GPU_SIZE_MB,
9 get_sequence_parallelism_threshold,
10 )
11
12
13 class TestGetSequenceParallelismThreshold:
14 """Tests for get_sequence_parallelism_threshold function."""
15
16 def test_non_cuda_returns_none(self, mock_cuda_platform):
17 """Non-CUDA platforms should return None."""
18 with mock_cuda_platform(is_cuda=False):
19 result = get_sequence_parallelism_threshold(
20 hidden_size=8192, tp_size=2, element_size=2
21 )
22 assert result is None
23
24 def test_unsupported_device_capability_returns_none(self, mock_cuda_platform):
25 """Unsupported device capabilities (e.g., sm80) should return None."""
26 with mock_cuda_platform(capability=(8, 0)):
27 result = get_sequence_parallelism_threshold(
28 hidden_size=8192, tp_size=2, element_size=2
29 )
30 assert result is None
31
32 def test_small_hidden_size_returns_none(self, mock_cuda_platform):
33 """H100 with hidden_size below threshold should return None."""
34 with mock_cuda_platform(capability=(9, 0)):
35 result = get_sequence_parallelism_threshold(
36 hidden_size=4096,
37 tp_size=2,
38 element_size=2, # 4096 < 8192
39 )
40 assert result is None
41
42 def test_h100_large_model_returns_threshold(self, mock_cuda_platform):
43 """H100 with large enough hidden_size should return calculated threshold."""
44 with mock_cuda_platform(capability=(9, 0)):
45 hidden_size = 8192
46 tp_size = 2
47 element_size = 2 # float16/bfloat16
48
49 result = get_sequence_parallelism_threshold(
50 hidden_size=hidden_size,
51 tp_size=tp_size,
52 element_size=element_size,
53 )
54
55 # Verify calculation: (8 * 2 * 1024 * 1024) // (8192 * 2) = 1024
56 MiB = 1024 * 1024
57 expected = int(
58 (SP_MIN_PER_GPU_SIZE_MB[90] * tp_size * MiB)
59 // (hidden_size * element_size)
60 )
61 assert result == expected
62 assert result == 1024
63
64 @pytest.mark.parametrize(
65 "hidden_size,tp_size,element_size,expected",
66 [
67 # Boundary: exactly at min hidden size threshold, tp_size=1
68 # (8 * 1 * 1024 * 1024) // (8192 * 2) = 512
69 (8192, 1, 2, 512),
70 # Larger hidden size reduces token threshold
71 # (8 * 1 * 1024 * 1024) // (16384 * 2) = 256
72 (16384, 1, 2, 256),
73 # Larger tp_size increases token threshold
74 # (8 * 4 * 1024 * 1024) // (8192 * 2) = 2048
75 (8192, 4, 2, 2048),
76 # Larger element_size (fp32) reduces token threshold
77 # (8 * 2 * 1024 * 1024) // (8192 * 4) = 512
78 (8192, 2, 4, 512),
79 ],
80 )
81 def test_threshold_calculation_variations(
82 self, mock_cuda_platform, hidden_size, tp_size, element_size, expected
83 ):
84 """Test threshold calculation with various parameter combinations."""
85 with mock_cuda_platform(capability=(9, 0)):
86 result = get_sequence_parallelism_threshold(
87 hidden_size=hidden_size,
88 tp_size=tp_size,
89 element_size=element_size,
90 )
91 assert result == expected
92
93 def test_hidden_size_boundary(self, mock_cuda_platform):
94 """Test behavior at the exact hidden_size boundary."""
95 with mock_cuda_platform(capability=(9, 0)):
96 # Just below threshold
97 result = get_sequence_parallelism_threshold(
98 hidden_size=SP_MIN_HIDDEN_SIZE[90] - 1,
99 tp_size=2,
100 element_size=2,
101 )
102 assert result is None
103
104 # Exactly at threshold
105 result = get_sequence_parallelism_threshold(
106 hidden_size=SP_MIN_HIDDEN_SIZE[90],
107 tp_size=2,
108 element_size=2,
109 )
110 assert result is not None
111
112
113 # XPU-specific constants (must match sequence_parallelism.py values)
114 _XPU_MIN_HIDDEN_SIZE = 4096
115 _XPU_MIN_PER_GPU_SIZE_MB = 8.0
116
117
118 class TestGetSequenceParallelismThresholdXPU:
119 """Tests for get_sequence_parallelism_threshold on XPU platform."""
120
121 def test_xpu_small_hidden_size_returns_none(self, mock_xpu_platform):
122 """XPU with hidden_size below threshold should return None."""
123 with mock_xpu_platform():
124 result = get_sequence_parallelism_threshold(
125 hidden_size=_XPU_MIN_HIDDEN_SIZE - 1,
126 tp_size=2,
127 element_size=2,
128 )
129 assert result is None
130
131 def test_xpu_large_model_returns_threshold(self, mock_xpu_platform):
132 """XPU with hidden_size >= threshold should return calculated value."""
133 with mock_xpu_platform():
134 hidden_size = _XPU_MIN_HIDDEN_SIZE
135 tp_size = 2
136 element_size = 2
137 result = get_sequence_parallelism_threshold(
138 hidden_size=hidden_size,
139 tp_size=tp_size,
140 element_size=element_size,
141 )
142 # (8 * 2 * 1024 * 1024) // (4096 * 2) = 2048
143 MiB = 1024 * 1024
144 expected = int(
145 (_XPU_MIN_PER_GPU_SIZE_MB * tp_size * MiB) // (hidden_size * element_size)
146 )
147 assert result == expected
148 assert result == 2048
149
150 @pytest.mark.parametrize(
151 "hidden_size,tp_size,element_size,expected",
152 [
153 # (8 * 1 * 1024 * 1024) // (4096 * 2) = 1024
154 (4096, 1, 2, 1024),
155 # (8 * 4 * 1024 * 1024) // (4096 * 2) = 4096
156 (4096, 4, 2, 4096),
157 # (8 * 2 * 1024 * 1024) // (8192 * 2) = 1024
158 (8192, 2, 2, 1024),
159 # (8 * 2 * 1024 * 1024) // (4096 * 4) = 1024
160 (4096, 2, 4, 1024),
161 ],
162 )
163 def test_xpu_threshold_calculation_variations(
164 self, mock_xpu_platform, hidden_size, tp_size, element_size, expected
165 ):
166 """Test XPU threshold calculation with various parameter combinations."""
167 with mock_xpu_platform():
168 result = get_sequence_parallelism_threshold(
169 hidden_size=hidden_size,
170 tp_size=tp_size,
171 element_size=element_size,
172 )
173 assert result == expected
174
175 def test_xpu_hidden_size_boundary(self, mock_xpu_platform):
176 """Test behavior at the exact XPU hidden_size boundary."""
177 with mock_xpu_platform():
178 # Just below threshold
179 result = get_sequence_parallelism_threshold(
180 hidden_size=_XPU_MIN_HIDDEN_SIZE - 1,
181 tp_size=2,
182 element_size=2,
183 )
184 assert result is None
185
186 # Exactly at threshold
187 result = get_sequence_parallelism_threshold(
188 hidden_size=_XPU_MIN_HIDDEN_SIZE,
189 tp_size=2,
190 element_size=2,
191 )
192 assert result is not None