Coverage for tests/simulator/test_simulator_energy.py: 100%
146 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-09 04:47 +0000
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-09 04:47 +0000
1import sys
2import os
3import pytest
5from dataclasses import replace
7# Add current path
8sys.path.append(os.getcwd())
10from tests.test_utils import temp_sys_path
12with temp_sys_path("simulator", "streamwise"):
13 from constants import DEFAULT_WORKFLOW_CONFIG
15 from sim_types import GPUType
16 from sim_types import Model
17 from sim_types import Objective
18 from sim_types import Solver
20 from data_loading import load_latency_data
21 from data_loading import load_power_data
23 from auto_model_allocator import AutoModelAllocator
24 from model_provisioner.greedy import GreedyAllocator
25 from model_provisioner.naive_baseline import NaiveAllocator
27 from model_provisioner.policies import NAIVE_POLICY
28 from model_provisioner.policies import STREAMWISE_POLICY
31def test_energy() -> None:
32 latency_data = load_latency_data("simulator/data/")
33 power_data = load_power_data("simulator/data/")
35 # 8 A100 + 8 H100
36 allocator = GreedyAllocator(
37 workflow=DEFAULT_WORKFLOW_CONFIG,
38 latency_data=latency_data,
39 power_data=power_data,
40 policy=STREAMWISE_POLICY,
41 )
42 result = allocator.allocate(
43 num_gpus={GPUType.A100: 8, GPUType.H100: 8},
44 )
45 assert result.gpus_used[GPUType.A100] == 8
46 assert result.gpus_used[GPUType.H100] == 8
47 assert 0 < result.tbf_s < result.ttff_s < result.total_time_s
48 assert 0 < result.total_energy
49 assert 0 < result.cost
52def test_energy_8A_0H() -> None:
53 """8 A100."""
54 latency_data = load_latency_data("simulator/data/")
55 power_data = load_power_data("simulator/data/")
57 allocator = GreedyAllocator(
58 workflow=DEFAULT_WORKFLOW_CONFIG,
59 latency_data=latency_data,
60 power_data=power_data,
61 )
62 result = allocator.allocate(
63 num_gpus={GPUType.A100: 8},
64 )
65 assert result.gpus_used[GPUType.A100] == 8
66 assert result.gpus_used.get(GPUType.H100, 0) == 0
67 assert 0 < result.tbf_s < result.ttff_s < result.total_time_s
68 assert 0 < result.total_energy
71def test_energy_A() -> None:
72 """A100 combinations."""
73 latency_data = load_latency_data("simulator/data/")
74 power_data = load_power_data("simulator/data/")
76 allocator = GreedyAllocator(
77 workflow=DEFAULT_WORKFLOW_CONFIG,
78 latency_data=latency_data,
79 power_data=power_data,
80 )
81 for num_a100s in range(8, 64 + 1, 8):
82 result = allocator.allocate(
83 num_gpus={GPUType.A100: num_a100s},
84 )
85 assert result.gpus_used[GPUType.A100] == num_a100s
86 assert result.gpus_used.get(GPUType.H100, 0) == 0
87 assert 0 < result.tbf_s < result.ttff_s < result.total_time_s
90def test_energy_0A_8H() -> None:
91 """8 H100."""
92 latency_data = load_latency_data("simulator/data/")
93 power_data = load_power_data("simulator/data/")
95 allocator = GreedyAllocator(
96 workflow=DEFAULT_WORKFLOW_CONFIG,
97 latency_data=latency_data,
98 power_data=power_data,
99 )
100 result = allocator.allocate(
101 num_gpus={GPUType.H100: 8},
102 verbose=True,
103 )
104 assert result.gpus_used.get(GPUType.A100, 0) == 0
105 assert result.gpus_used[GPUType.H100] == 8
106 assert 0 < result.tbf_s < result.ttff_s < result.total_time_s
108 video_seconds = DEFAULT_WORKFLOW_CONFIG.total_video_seconds
109 expected_length_upper = 4 * 60 * 60 # 4 hours
110 expected_length_lower = 2 * 60 * 60 # 2 hours
111 total_frames = DEFAULT_WORKFLOW_CONFIG.total_frames[Model.FT]
112 assert expected_length_lower <= result.total_time_s <= expected_length_upper
113 assert expected_length_lower - video_seconds <= result.ttff_s <= expected_length_upper - video_seconds
114 assert expected_length_lower / total_frames <= result.tbf_s <= expected_length_upper / total_frames
116 idle_energy = 8 * power_data.gpus[GPUType.H100].idle * result.total_time_s
117 active_energy = 8 * power_data.gpus[GPUType.H100].tdp * result.total_time_s
118 assert idle_energy <= result.total_energy <= active_energy
121def test_energy_H() -> None:
122 """H100 combinations."""
123 latency_data = load_latency_data("simulator/data/")
124 power_data = load_power_data("simulator/data/")
126 allocator = GreedyAllocator(
127 workflow=DEFAULT_WORKFLOW_CONFIG,
128 latency_data=latency_data,
129 power_data=power_data,
130 )
131 for num_h100s in range(8, 64 + 1, 8):
132 result = allocator.allocate(
133 num_gpus={GPUType.H100: num_h100s},
134 )
135 assert result.gpus_used.get(GPUType.A100, 0) == 0
136 assert result.gpus_used[GPUType.H100] == num_h100s
137 assert 0 < result.tbf_s < result.ttff_s < result.total_time_s
140def test_energy_0A_8H_naive() -> None:
141 latency_data = load_latency_data("simulator/data/")
142 power_data = load_power_data("simulator/data/")
144 allocator = NaiveAllocator(
145 workflow=DEFAULT_WORKFLOW_CONFIG,
146 latency_data=latency_data,
147 power_data=power_data,
148 policy=NAIVE_POLICY,
149 )
150 # 8 H100
151 result = allocator.allocate(
152 num_gpus={GPUType.H100: 8},
153 verbose=True,
154 )
155 assert result.gpus_used.get(GPUType.A100, 0) == 0
156 assert result.gpus_used.get(GPUType.H100, 0) == 8
157 assert result.total_time_s > 0
158 assert result.total_energy > 0
161def test_energy_24A_0H() -> None:
162 latency_data = load_latency_data("simulator/data/")
163 power_data = load_power_data("simulator/data/")
165 allocator = GreedyAllocator(
166 workflow=DEFAULT_WORKFLOW_CONFIG,
167 latency_data=latency_data,
168 power_data=power_data,
169 )
171 # 24 A100 + 0 H100
172 result = allocator.allocate(
173 num_gpus={GPUType.A100: 24},
174 )
175 assert result.total_time_s > 0
176 assert result.gpus_used[GPUType.A100] == 24
177 assert result.gpus_used.get(GPUType.H100, 0) == 0
178 assert result.total_energy > 0
181def test_energy_0A_32H() -> None:
182 latency_data = load_latency_data("simulator/data/")
183 power_data = load_power_data("simulator/data/")
184 allocator = GreedyAllocator(
185 workflow=DEFAULT_WORKFLOW_CONFIG,
186 latency_data=latency_data,
187 power_data=power_data,
188 )
189 # 0 A100 + 32 H100
190 result = allocator.allocate(
191 num_gpus={GPUType.H100: 32},
192 )
193 assert result.total_time_s > 0
194 assert result.gpus_used.get(GPUType.A100, 0) == 0
195 assert result.gpus_used[GPUType.H100] == 32
196 assert result.total_energy > 0
199def test_energy_16A_32H() -> None:
200 latency_data = load_latency_data("simulator/data/")
201 power_data = load_power_data("simulator/data/")
202 allocator = GreedyAllocator(
203 workflow=DEFAULT_WORKFLOW_CONFIG,
204 latency_data=latency_data,
205 power_data=power_data,
206 )
207 # 16 A100 + 32 H100
208 result = allocator.allocate(
209 num_gpus={GPUType.A100: 16, GPUType.H100: 32},
210 verbose=True,
211 )
212 assert result.total_time_s > 0
213 assert result.gpus_used[GPUType.A100] == 16
214 assert result.gpus_used[GPUType.H100] == 32
215 assert result.total_energy > 0
218def test_energy_8A_64H() -> None:
219 # 8 A100 + 64 H100
220 latency_data = load_latency_data("simulator/data/")
221 power_data = load_power_data("simulator/data/")
222 allocator = AutoModelAllocator(
223 workflow=DEFAULT_WORKFLOW_CONFIG,
224 latency_data=latency_data,
225 power_data=power_data,
226 policy=NAIVE_POLICY,
227 )
228 result = allocator.allocate(
229 num_gpus={GPUType.A100: 8, GPUType.H100: 64},
230 )
231 assert result.gpus_used[GPUType.A100] == 8
232 assert result.gpus_used[GPUType.H100] == 64
233 assert 0 < result.tbf_s < result.ttff_s < result.total_time_s
234 assert 0 < result.total_energy
237def test_energy_16H_naive() -> None:
238 """16 H100 Naive."""
239 latency_data = load_latency_data("simulator/data/")
240 power_data = load_power_data("simulator/data/")
241 allocator = NaiveAllocator(
242 workflow=DEFAULT_WORKFLOW_CONFIG,
243 latency_data=latency_data,
244 power_data=power_data,
245 )
246 result = allocator.allocate(
247 num_gpus={GPUType.H100: 16},
248 verbose=True,
249 )
250 assert result.gpus_used.get(GPUType.A100, 0) == 0
251 assert result.gpus_used[GPUType.H100] == 16
252 assert 0 < result.tbf_s < result.ttff_s < result.total_time_s
253 assert 0 < result.total_energy
256def test_energy_0() -> None:
257 """No GPUs."""
258 latency_data = load_latency_data("simulator/data/")
259 power_data = load_power_data("simulator/data/")
260 allocator = GreedyAllocator(
261 workflow=DEFAULT_WORKFLOW_CONFIG,
262 latency_data=latency_data,
263 power_data=power_data,
264 )
265 with pytest.raises(AssertionError, match="Total number of GPUs must be at least 8"):
266 allocator.allocate(num_gpus={})
269def test_energy_naive_parallelism() -> None:
270 """Error from simulation."""
271 latency_data = load_latency_data("simulator/data/")
272 power_data = load_power_data("simulator/data/")
274 policy = replace(STREAMWISE_POLICY)
275 policy.objective = Objective.TTFF
276 policy.solver = Solver.NAIVE
277 allocator = AutoModelAllocator(
278 workflow=DEFAULT_WORKFLOW_CONFIG,
279 latency_data=latency_data,
280 power_data=power_data,
281 policy=policy,
282 )
283 result = allocator.allocate(
284 num_gpus={GPUType.A100: 1280, GPUType.H100: 576},
285 )
286 assert 1280 - 8 <= result.gpus_used[GPUType.A100] <= 1280
287 assert 576 - 8 <= result.gpus_used[GPUType.H100] <= 576
288 assert 0 < result.tbf_s < result.ttff_s < result.total_time_s
289 assert 0 < result.total_energy