code: def on_loop_end(self) -> None:
      avg_make_experience_duration = all_reduce_mean(
          self.make_experience_timer.duration, self.world_size
      )
      avg_overall_duration = all_reduce_mean(
          self.batch_timer.duration, self.world_size
      )
      avg_send_duration = all_reduce_mean(
          self.send_timer.duration, self.world_size
      )
  
      avg_throughput = (
          self.total_samples
          * self.world_size
          / (avg_overall_duration + 1e-12)
      )
      avg_make_experience_tflops = (
          self.make_experience_flop
          / 1e12
          / (avg_make_experience_duration + 1e-12)
      )
      avg_time_per_sample = (avg_overall_duration + 1e-12) / (
          self.total_samples * self.world_size
      )
      avg_make_experience_time_per_sample = (
          avg_make_experience_duration + 1e-12
      ) / (self.total_samples * self.world_size)
      avg_send_time_per_sample = (avg_send_duration + 1e-12) / (
          self.total_samples * self.world_size
      )
  
      print_rank_0(
          "Making Experience Performance Summary:\n"
          + f"Throughput: {avg_throughput:.3f} samples/sec\n"
          + f"TFLOPS per GPU: {avg_make_experience_tflops:.3f}\n"
          + f"Sample time (overall): {avg_time_per_sample:.3f} s\n"
          + f"Sample time (make experience): {avg_make_experience_time_per_sample:.3f} s, {avg_make_experience_time_per_sample/avg_time_per_sample*100:.2f}%\n"
          + f"Sample time (send): {avg_send_time_per_sample:.3f} s, {avg_send_time_per_sample/avg_time_per_sample*100:.2f}%\n"
      )
  
imports: from time import time
  from typing import Optional
  import torch
  import torch.distributed
  from coati.experience_maker import Experience
  from .base import MakerCallback, TrainerCallback
label_desc: Use image node_id 8 for calling the ExperienceMakerPerformanceEvaluator obj's underlying member method code with example usage: obj.on_loop_end() without return types