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

1import sys 

2import os 

3import pytest 

4 

5from dataclasses import replace 

6 

7# Add current path 

8sys.path.append(os.getcwd()) 

9 

10from tests.test_utils import temp_sys_path 

11 

12with temp_sys_path("simulator", "streamwise"): 

13 from constants import DEFAULT_WORKFLOW_CONFIG 

14 

15 from sim_types import GPUType 

16 from sim_types import Model 

17 from sim_types import Objective 

18 from sim_types import Solver 

19 

20 from data_loading import load_latency_data 

21 from data_loading import load_power_data 

22 

23 from auto_model_allocator import AutoModelAllocator 

24 from model_provisioner.greedy import GreedyAllocator 

25 from model_provisioner.naive_baseline import NaiveAllocator 

26 

27 from model_provisioner.policies import NAIVE_POLICY 

28 from model_provisioner.policies import STREAMWISE_POLICY 

29 

30 

31def test_energy() -> None: 

32 latency_data = load_latency_data("simulator/data/") 

33 power_data = load_power_data("simulator/data/") 

34 

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 

50 

51 

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/") 

56 

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 

69 

70 

71def test_energy_A() -> None: 

72 """A100 combinations.""" 

73 latency_data = load_latency_data("simulator/data/") 

74 power_data = load_power_data("simulator/data/") 

75 

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 

88 

89 

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/") 

94 

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 

107 

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 

115 

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 

119 

120 

121def test_energy_H() -> None: 

122 """H100 combinations.""" 

123 latency_data = load_latency_data("simulator/data/") 

124 power_data = load_power_data("simulator/data/") 

125 

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 

138 

139 

140def test_energy_0A_8H_naive() -> None: 

141 latency_data = load_latency_data("simulator/data/") 

142 power_data = load_power_data("simulator/data/") 

143 

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 

159 

160 

161def test_energy_24A_0H() -> None: 

162 latency_data = load_latency_data("simulator/data/") 

163 power_data = load_power_data("simulator/data/") 

164 

165 allocator = GreedyAllocator( 

166 workflow=DEFAULT_WORKFLOW_CONFIG, 

167 latency_data=latency_data, 

168 power_data=power_data, 

169 ) 

170 

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 

179 

180 

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 

197 

198 

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 

216 

217 

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 

235 

236 

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 

254 

255 

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={}) 

267 

268 

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/") 

273 

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