code: def monitor(
      queue: Queue,
      info: Dict[str, Any],
      logging_interval: int,
      cuda_is_available: bool,
  ) -> None:
      """Monitors hardware resource use.
  
      Collects system specific metrics (CPU/CUDA, CPU/CUDA memory) at a `logging_interval` interval and pushes
      results back to the parent process.
  
      Args:
          queue: queue from which we can push and retrieve messages sent to the function targeted by the thread.
          info: dictionary containing system resource usage information about the running process.
          logging_interval: time interval at which we will poll the system for usage metrics.
          cuda_is_available: stores torch.cuda.is_available().
      """
      info["global_cpu_memory_available"] = [
          psutil.virtual_memory().available
      ]
      info["global_cpu_utilization"] = [psutil.cpu_percent()]
      # get the pid of the parent process.
      tracked_process = psutil.Process(os.getpid())
  
      # will return a meaningless 0 value on the first call because `interval` arg is set to None.
      tracked_process.cpu_percent(interval=logging_interval)
      with tracked_process.oneshot():
          info["cpu_utilization"] = [
              tracked_process.cpu_percent() / info["num_cpu"]
          ]
          info["cpu_memory_usage"] = [
              tracked_process.memory_full_info().uss
          ]
          try:
              info["num_accessible_cpus"] = len(
                  tracked_process.cpu_affinity()
              )
          except Exception:
              pass
  
      while True:
          try:
              message = queue.get(block=False)
              if isinstance(message, str):
                  if message == STOP_MESSAGE:
                      # synchronize CUDA to get accurate timing for jobs running on GPU.
                      if cuda_is_available:
                          torch.cuda.synchronize()
                      queue.put(info)
                      return
              else:
                  queue.put(message)
          except EmptyQueueException:
              pass
          if cuda_is_available:
              gpu_infos = GPUStatCollection.new_query()
              for i, gpu_info in enumerate(gpu_infos):
                  gpu_key = f"cuda_{i}"
                  info[f"{gpu_key}_memory_used"].append(
                      gpu_info.memory_used
                  )
          with tracked_process.oneshot():
              info["cpu_utilization"].append(
                  tracked_process.cpu_percent() / info["num_cpu"]
              )
              info["cpu_memory_usage"].append(
                  tracked_process.memory_full_info().uss
              )
          info["global_cpu_memory_available"].append(
              psutil.virtual_memory().available
          )
          info["global_cpu_utilization"].append(psutil.cpu_percent())
          time.sleep(logging_interval)
  
imports: import contextlib
  import glob
  import logging
  import os
  import shutil
  import threading
  import time
  from queue import Empty
  from queue import Queue
  from subprocess import PIPE, Popen
  from typing import Any, Dict, List
  from xml.etree.ElementTree import fromstring
  import psutil
  import torch
  from cpuinfo import get_cpu_info
  from gpustat.core import GPUStatCollection
  from ludwig.benchmarking.profiler_dataclasses import profiler_dataclass_to_flat_dict, TorchProfilerMetrics
  from ludwig.benchmarking.reporting import get_metrics_from_system_usage_profiler, get_metrics_from_torch_profiler
  from ludwig.constants import LUDWIG_TAG
  from ludwig.globals import LUDWIG_VERSION
  from ludwig.utils.data_utils import save_json
label_desc: Use image node_id 2 for calling a global function with example usage: monitor(queue, info, logging_interval, cuda_is_available) without return types