class_docstr: Track system resource (hardware and software) usage.
  
  Warning: If `use_torch_profiler=True` while profiling on CUDA, it's not possible to benchmark DataLoaders
  with `num_workers > 0` due to CUDA multiprocessing limitations. See warning under `profile` class
  definition: https://github.com/pytorch/pytorch/blob/master/torch/autograd/profiler.py
  
  Attributes:
      tag: a string tag describing the code block/function that we're tracking.
          (e.g trainer.train, preprocessing, etc.)
      output_dir: path where metrics are saved.
      logging_interval: time interval in seconds at which system is polled for resource usage.
class_docstr_tok: ["Track","system","resource","(","hardware","and","software",")","usage",".","Warning",":","If","`","use_torch_profiler=True","`","while","profiling","on","CUDA",",","it","'s","not","possible","to","benchmark","DataLoaders","with","`","num_workers",">","0","`","due","to","CUDA","multiprocessing","limitations",".","See","warning","under","`","profile","`","class","definition",":","https",":","\/\/github.com\/pytorch\/pytorch\/blob\/master\/torch\/autograd\/profiler.py","Attributes",":","tag",":","a","string","tag","describing","the","code","block\/function","that","we","'re","tracking",".","(","e.g","trainer.train",",","preprocessing",",","etc",".",")","output_dir",":","path","where","metrics","are","saved",".","logging_interval",":","time","interval","in","seconds","at","which","system","is","polled","for","resource","usage","."]
code: def __init__(
      self,
      tag: str,
      use_torch_profiler: bool,
      output_dir: str,
      logging_interval: float = 0.1,
  ) -> None:
      self.tag = tag
      self._tag = LUDWIG_TAG + self.tag
      self.use_torch_profiler = use_torch_profiler
      self.output_dir = output_dir
      self.logging_interval = logging_interval
      self.cuda_is_available = torch.cuda.is_available()
      self.launched = False
      if self.use_torch_profiler:
          self.profiler_activities = [
              torch.profiler.ProfilerActivity.CPU
          ]
          if self.cuda_is_available:
              self.profiler_activities.append(
                  torch.profiler.ProfilerActivity.CUDA
              )
      os.makedirs(os.path.join(self.output_dir), exist_ok=True)
  
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 1 to create a new LudwigProfiler object from inherited base classes: contextlib with example: obj = LudwigProfiler(tag, use_torch_profiler, output_dir, logging_interval)