Skip to content

Commit

Permalink
Merge pull request #214 from mathoudebine/fix/get-best-gpu-for-stats
Browse files Browse the repository at this point in the history
Detect and handle multiple GPUs better
  • Loading branch information
mathoudebine authored May 12, 2023
2 parents 2ec2d36 + 45f5852 commit 04deaf4
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 20 deletions.
1 change: 1 addition & 0 deletions external/LibreHardwareMonitor/test_librehardwaremonitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
handle.IsControllerEnabled = True
handle.IsNetworkEnabled = True
handle.IsStorageEnabled = True
handle.IsPsuEnabled = True
handle.Open()

for hw in handle.Hardware:
Expand Down
2 changes: 1 addition & 1 deletion library/lcd/lcd_comm.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ def openSerial(self):
if self.com_port == 'AUTO':
lcd_com_port = self.auto_detect_com_port()
if not lcd_com_port:
logger.error("Cannot find COM port automatically, please set it manually in config.yaml")
logger.error("Cannot find COM port automatically, please run Configuration again and select COM port manually")
try:
sys.exit(0)
except:
Expand Down
99 changes: 80 additions & 19 deletions library/sensors/sensors_librehardwaremonitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,79 @@
logger.info("Found Network interface: %s" % hardware.Name)


def get_hw_and_update(hwtype: Hardware.HardwareType) -> Hardware.Hardware:
def get_hw_and_update(hwtype: Hardware.HardwareType, name: str = None) -> Hardware.Hardware:
for hardware in handle.Hardware:
if hardware.HardwareType == hwtype:
hardware.Update()
return hardware
if (name and hardware.Name == name) or not name:
hardware.Update()
return hardware
return None


def get_gpu_name() -> str:
# Determine which GPU to use, in case there are multiple : try to avoid using discrete GPU for stats
hw_gpus = []
for hardware in handle.Hardware:
if hardware.HardwareType == Hardware.HardwareType.GpuNvidia \
or hardware.HardwareType == Hardware.HardwareType.GpuAmd \
or hardware.HardwareType == Hardware.HardwareType.GpuIntel:
hw_gpus.append(hardware)

if len(hw_gpus) == 0:
# No supported GPU found on the system
logger.warning("No supported GPU found")
return ""
elif len(hw_gpus) == 1:
# Found one supported GPU
logger.debug("Found one supported GPU: %s" % hw_gpus[0].Name)
return str(hw_gpus[0].Name)
else:
# Found multiple GPUs, try to determine which one to use
amd_gpus = 0
intel_gpus = 0
nvidia_gpus = 0

gpu_to_use = ""

# Count GPUs by manufacturer
for gpu in hw_gpus:
if gpu.HardwareType == Hardware.HardwareType.GpuAmd:
amd_gpus += 1
elif gpu.HardwareType == Hardware.HardwareType.GpuIntel:
intel_gpus += 1
elif gpu.HardwareType == Hardware.HardwareType.GpuNvidia:
nvidia_gpus += 1

logger.warning(
"Found %d GPUs on your system (%d AMD / %d Nvidia / %d Intel). Auto identify which GPU to use." % (
len(hw_gpus), amd_gpus, nvidia_gpus, intel_gpus))

if nvidia_gpus >= 1:
# One (or more) Nvidia GPU: use first available for stats
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuNvidia).Name
elif amd_gpus == 1:
# No Nvidia GPU, only one AMD GPU: use it
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuAmd).Name
elif amd_gpus > 1:
# No Nvidia GPU, several AMD GPUs found: try to use the real GPU but not the APU integrated in CPU
for gpu in hw_gpus:
if gpu.HardwareType == Hardware.HardwareType.GpuAmd:
for sensor in gpu.Sensors:
if sensor.SensorType == Hardware.SensorType.Load and str(sensor.Name).startswith("GPU Core"):
# Found load sensor for this GPU: assume it is main GPU and use it for stats
gpu_to_use = gpu.Name
else:
# No AMD or Nvidia GPU: there are several Intel GPUs, use first available for stats
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuIntel).Name

if gpu_to_use:
logger.debug("This GPU will be used for stats: %s" % gpu_to_use)
else:
logger.warning("No supported GPU found (no GPU with load sensor)")

return gpu_to_use


def get_net_interface_and_update(if_name: str) -> Hardware.Hardware:
for hardware in handle.Hardware:
if hardware.HardwareType == Hardware.HardwareType.Network and hardware.Name == if_name:
Expand Down Expand Up @@ -173,13 +238,16 @@ def temperature() -> float:


class Gpu(sensors.Gpu):
@staticmethod
def stats() -> Tuple[float, float, float, float]: # load (%) / used mem (%) / used mem (Mb) / temp (°C)
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuAmd)
# GPU to use is detected once, and its name is saved for future sensors readings
gpu_name = ""

@classmethod
def stats(cls) -> Tuple[float, float, float, float]: # load (%) / used mem (%) / used mem (Mb) / temp (°C)
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuAmd, cls.gpu_name)
if gpu_to_use is None:
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuNvidia)
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuNvidia, cls.gpu_name)
if gpu_to_use is None:
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuIntel)
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuIntel, cls.gpu_name)
if gpu_to_use is None:
# GPU not supported
return math.nan, math.nan, math.nan, math.nan
Expand All @@ -206,17 +274,10 @@ def stats() -> Tuple[float, float, float, float]: # load (%) / used mem (%) / u

return load, (used_mem / total_mem * 100.0), used_mem, temp

@staticmethod
def is_available() -> bool:
found_amd = (get_hw_and_update(Hardware.HardwareType.GpuAmd) is not None)
found_nvidia = (get_hw_and_update(Hardware.HardwareType.GpuNvidia) is not None)
found_intel = (get_hw_and_update(Hardware.HardwareType.GpuIntel) is not None)

if (found_amd and (found_nvidia or found_intel)) or (found_nvidia and found_intel):
logger.info(
"Found multiple GPUs on your system. Will use dedicated GPU (AMD/Nvidia) for stats if possible.")

return found_amd or found_nvidia or found_intel
@classmethod
def is_available(cls) -> bool:
cls.gpu_name = get_gpu_name()
return bool(cls.gpu_name)


class Memory(sensors.Memory):
Expand Down

0 comments on commit 04deaf4

Please sign in to comment.