class_docstr: This worker will send requests to a backend process, and measure the
  throughput and latency of those requests as well as GPU utilization.
class_docstr_tok: ["This","worker","will","send","requests","to","a","backend","process",",","and","measure","the","throughput","and","latency","of","those","requests","as","well","as","GPU","utilization","."]
code: def run(self):
      # Lock for writing to metrics_dict
      metrics_lock = threading.Lock()
      requests_thread = threading.Thread(target=self._send_requests)
      metrics_thread = threading.Thread(
          target=self._run_metrics, args=(metrics_lock,)
      )
      gpu_utilization_thread = threading.Thread(
          target=self._run_gpu_utilization, args=(metrics_lock,)
      )
  
      requests_thread.start()
      metrics_thread.start()
  
      # only start polling GPU utilization after the warmup request is complete
      self.warmup_event.wait()
      gpu_utilization_thread.start()
  
      requests_thread.join()
      metrics_thread.join()
      gpu_utilization_thread.join()
  
imports: import argparse
  import asyncio
  import os.path
  import subprocess
  import threading
  import time
  from concurrent.futures import ThreadPoolExecutor
  from queue import Empty
  import numpy
  import pandas
  import torch
  import torch.multiprocessing
label_desc: Use image node_id 5 for calling the FrontendWorker obj's underlying member method code with example usage: obj.run() without return types