code: def _combine_and_average_training_metrics(
      context: det.core.DistributedContext,
      per_batch_metrics: List[Dict[str, Any]],
  ) -> List[Dict[str, Any]]:
      assert (
          context.size > 1
      ), "Can only average training metrics in multi-GPU training."
      metrics_timeseries = util._list_to_dict(per_batch_metrics)
  
      # Gather metrics across ranks onto rank 0 slot.
      # The combined_timeseries is: dict[metric_name] -> 2d-array.
      # A measurement is accessed via combined_timeseries[metric_name][process_idx][batch_idx].
      (
          combined_timeseries,
          combined_num_batches,
      ) = _combine_metrics_across_processes(
          context,
          metrics_timeseries,
          num_batches=len(per_batch_metrics),
      )
  
      if context.rank == 0:
          # We can safely cast variables here because this is all happening on the chief, which
          # is where we gather metrics.
          combined_timeseries = cast(
              Dict[str, List[List[Any]]], combined_timeseries
          )
          combined_num_batches = cast(List[int], combined_num_batches)
  
          per_batch_metrics = _average_training_metrics(
              combined_timeseries, combined_num_batches
          )
      return per_batch_metrics
  
file_path: determined/harness/determined/pytorch/_metric_utils.py
imports: import logging
  from typing import Any, Dict, List, Optional, Tuple, Union, cast
  import numpy
  import torch
  import determined
  from determined import pytorch, util
label_desc: Use image node_id 4 for calling a global function with example usage: _combine_and_average_training_metrics(context, per_batch_metrics) and returns: per_batch_metrics