code: def _get_gpu_stats(self):
      if not self._gpustat:
          return {}
  
      # per process memory query id slow, so we only call it once per reporting period,
      # On the rest of the samples we return the previous memory measurement
  
      # update mem used by our process and sub processes
      if (
          self._gpu_memory_per_process
          and self._process_info
          and (
              not self._last_process_pool.get("gpu")
              or (time() - self._last_process_pool["gpu"][0])
              >= self._report_frequency
          )
      ):
          gpu_mem = {}
          # noinspection PyBroadException
          try:
              gpu_stat = self._gpustat.new_query(per_process_stats=True)
          except Exception:
              gpu_stat = self._gpustat.new_query(
                  per_process_stats=False
              )
  
          for i, g in enumerate(gpu_stat.gpus):
              # if processes is None, that means we can't query GPU memory usage per proces, so we can stop
              if g.processes is None:
                  self._gpu_memory_per_process = False
                  break
              # only monitor the active gpu's, if none were selected, monitor everything
              if self._skip_nonactive_gpu(i, g):
                  continue
  
              gpu_mem[i] = 0
              for p in g.processes:
                  if (
                      p is not None
                      and p["pid"] in self._last_process_id_list
                  ):
                      gpu_mem[i] += p.get("gpu_memory_usage", 0)
  
          self._last_process_pool["gpu"] = time(), gpu_mem
      else:
          # if we do no need to update the memory usage, run global query
          # if we have no parent process (backward compatibility), return global stats
          gpu_stat = self._gpustat.new_query(per_process_stats=False)
          gpu_mem = (
              self._last_process_pool["gpu"][1]
              if self._last_process_pool.get("gpu")
              else None
          )
  
      # generate the statistics dict for actual report
      stats = {}
  
      for i, g in enumerate(gpu_stat.gpus):
          # only monitor the active gpu's, if none were selected, monitor everything
          if self._skip_nonactive_gpu(i, g):
              continue
          stats["gpu_%d_temperature" % i] = float(g["temperature.gpu"])
          stats["gpu_%d_utilization" % i] = float(g["utilization.gpu"])
          stats["gpu_%d_mem_usage" % i] = (
              100.0 * float(g["memory.used"]) / float(g["memory.total"])
          )
          # already in MBs
          stats["gpu_%d_mem_free_gb" % i] = (
              float(g["memory.total"] - g["memory.used"]) / 1024
          )
          # use previously sampled process gpu memory, or global if it does not exist
          stats["gpu_%d_mem_used_gb" % i] = (
              float(gpu_mem[i] if gpu_mem else g["memory.used"]) / 1024
          )
  
      return stats
  
imports: import logging
  import os
  import platform
  import sys
  import warnings
  from time import time
  import psutil
  from pathlib2 import Path
  from typing import Text
  from .process.mp import BackgroundMonitor
  from ..backend_api import Session
  from ..binding.frameworks.tensorflow_bind import IsTensorboardInit
label_desc: Use image node_id 12 for calling the ResourceMonitor obj's underlying member method code with example usage: obj._get_gpu_stats() and returns: stats, dict