@@ -254,7 +254,14 @@ def aggregate_usage(self, start_time, end_time):
254254 """Aggregate usage metrics by account and time period."""
255255 rows = self .fetch_usage_records (start_time , end_time )
256256 agg = {}
257- totals = {'daily' : {}, 'monthly' : {}, 'yearly' : {}}
257+ totals = {
258+ 'daily' : {},
259+ 'monthly' : {},
260+ 'yearly' : {},
261+ 'daily_gpu' : {},
262+ 'monthly_gpu' : {},
263+ 'yearly_gpu' : {},
264+ }
258265 for row in rows :
259266 start = self ._to_datetime (row ['time_start' ])
260267 end = self ._to_datetime (row ['time_end' ] or row ['time_start' ])
@@ -271,20 +278,28 @@ def aggregate_usage(self, start_time, end_time):
271278 cpus = float (row .get ('cpus_alloc' ) or 0 )
272279 except (TypeError , ValueError ):
273280 cpus = 0.0
281+ gpus = self ._parse_tres (row .get ('tres_alloc' ), 'gpu' )
282+ if not gpus :
283+ gpus = self ._parse_tres (row .get ('tres_alloc' ), 'gres/gpu' )
274284
275285 totals ['daily' ][day ] = totals ['daily' ].get (day , 0.0 ) + cpus * dur_hours
276286 totals ['monthly' ][month ] = totals ['monthly' ].get (month , 0.0 ) + cpus * dur_hours
277287 totals ['yearly' ][year ] = totals ['yearly' ].get (year , 0.0 ) + cpus * dur_hours
288+ totals ['daily_gpu' ][day ] = totals ['daily_gpu' ].get (day , 0.0 ) + gpus * dur_hours
289+ totals ['monthly_gpu' ][month ] = totals ['monthly_gpu' ].get (month , 0.0 ) + gpus * dur_hours
290+ totals ['yearly_gpu' ][year ] = totals ['yearly_gpu' ].get (year , 0.0 ) + gpus * dur_hours
278291
279292 month_entry = agg .setdefault (month , {})
280293 acct_entry = month_entry .setdefault (
281294 account ,
282295 {
283296 'core_hours' : 0.0 ,
297+ 'gpu_hours' : 0.0 ,
284298 'users' : {},
285299 },
286300 )
287301 acct_entry ['core_hours' ] += cpus * dur_hours
302+ acct_entry ['gpu_hours' ] += gpus * dur_hours
288303 user_entry = acct_entry ['users' ].setdefault (
289304 user , {'core_hours' : 0.0 , 'jobs' : {}}
290305 )
@@ -345,6 +360,7 @@ def export_summary(self, start_time, end_time):
345360 'invoices' : [],
346361 }
347362 total_ch = 0.0
363+ total_gpu = 0.0
348364 total_cost = 0.0
349365
350366 rates_path = os .path .join (os .path .dirname (__file__ ), 'rates.json' )
@@ -407,11 +423,13 @@ def export_summary(self, start_time, end_time):
407423 {
408424 'account' : account ,
409425 'core_hours' : round (vals ['core_hours' ], 2 ),
426+ 'gpu_hours' : round (vals .get ('gpu_hours' , 0.0 ), 2 ),
410427 'cost' : round (acct_cost , 2 ),
411428 'users' : users ,
412429 }
413430 )
414431 total_ch += vals ['core_hours' ]
432+ total_gpu += vals .get ('gpu_hours' , 0.0 )
415433 total_cost += acct_cost
416434 start_dt = (
417435 datetime .fromisoformat (start_time )
@@ -427,18 +445,31 @@ def export_summary(self, start_time, end_time):
427445 'period' : f"{ start_dt .strftime ('%Y-%m-%d' )} to { end_dt .strftime ('%Y-%m-%d' )} " ,
428446 'total' : round (total_cost , 2 ),
429447 'core_hours' : round (total_ch , 2 ),
448+ 'gpu_hours' : round (total_gpu , 2 ),
430449 }
431450 summary ['daily' ] = [
432- {'date' : d , 'core_hours' : round (v , 2 )}
433- for d , v in sorted (totals ['daily' ].items ())
451+ {
452+ 'date' : d ,
453+ 'core_hours' : round (totals ['daily' ].get (d , 0.0 ), 2 ),
454+ 'gpu_hours' : round (totals .get ('daily_gpu' , {}).get (d , 0.0 ), 2 ),
455+ }
456+ for d in sorted (set (totals ['daily' ]) | set (totals .get ('daily_gpu' , {})))
434457 ]
435458 summary ['monthly' ] = [
436- {'month' : m , 'core_hours' : round (v , 2 )}
437- for m , v in sorted (totals ['monthly' ].items ())
459+ {
460+ 'month' : m ,
461+ 'core_hours' : round (totals ['monthly' ].get (m , 0.0 ), 2 ),
462+ 'gpu_hours' : round (totals .get ('monthly_gpu' , {}).get (m , 0.0 ), 2 ),
463+ }
464+ for m in sorted (set (totals ['monthly' ]) | set (totals .get ('monthly_gpu' , {})))
438465 ]
439466 summary ['yearly' ] = [
440- {'year' : y , 'core_hours' : round (v , 2 )}
441- for y , v in sorted (totals ['yearly' ].items ())
467+ {
468+ 'year' : y ,
469+ 'core_hours' : round (totals ['yearly' ].get (y , 0.0 ), 2 ),
470+ 'gpu_hours' : round (totals .get ('yearly_gpu' , {}).get (y , 0.0 ), 2 ),
471+ }
472+ for y in sorted (set (totals ['yearly' ]) | set (totals .get ('yearly_gpu' , {})))
442473 ]
443474 summary ['invoices' ] = self .fetch_invoices (start_time , end_time )
444475 return summary
0 commit comments