Skip to content

Commit 029adf3

Browse files
committed
Detect multiple GPUs
1 parent 6c34489 commit 029adf3

File tree

2 files changed

+78
-19
lines changed

2 files changed

+78
-19
lines changed

external/LibreHardwareMonitor/test_librehardwaremonitor.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
handle.IsControllerEnabled = True
4444
handle.IsNetworkEnabled = True
4545
handle.IsStorageEnabled = True
46+
handle.IsPsuEnabled = True
4647
handle.Open()
4748

4849
for hw in handle.Hardware:

library/sensors/sensors_librehardwaremonitor.py

Lines changed: 77 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,77 @@
8787
logger.info("Found Network interface: %s" % hardware.Name)
8888

8989

90-
def get_hw_and_update(hwtype: Hardware.HardwareType) -> Hardware.Hardware:
90+
def get_hw_and_update(hwtype: Hardware.HardwareType, name: str = None) -> Hardware.Hardware:
9191
for hardware in handle.Hardware:
9292
if hardware.HardwareType == hwtype:
93-
hardware.Update()
94-
return hardware
93+
if (name and hardware.Name == name) or not name:
94+
hardware.Update()
95+
return hardware
9596
return None
9697

9798

99+
def get_gpu_name() -> str:
100+
# Determine which GPU to use, in case there are multiple : try to avoid using discrete GPU for stats
101+
hw_gpus = []
102+
for hardware in handle.Hardware:
103+
if hardware.HardwareType == Hardware.HardwareType.GpuNvidia \
104+
or hardware.HardwareType == Hardware.HardwareType.GpuAmd \
105+
or hardware.HardwareType == Hardware.HardwareType.GpuIntel:
106+
hw_gpus.append(hardware)
107+
108+
if len(hw_gpus) == 0:
109+
# No supported GPU found on the system
110+
logger.debug("No supported GPU found")
111+
return ""
112+
elif len(hw_gpus) == 1:
113+
# Found one supported GPU
114+
logger.debug("Found one supported GPU: %s" % hw_gpus[0].Name)
115+
return str(hw_gpus[0].Name)
116+
else:
117+
# Found multiple GPUs, try to determine which one to use
118+
logger.warning(
119+
"Found multiple GPUs on your system. Will use dedicated GPU (AMD/Nvidia) for stats if possible.")
120+
amd_gpus = 0
121+
intel_gpus = 0
122+
nvidia_gpus = 0
123+
124+
gpu_to_use = None
125+
126+
# Count GPUs by manufacturer
127+
for gpu in hw_gpus:
128+
if gpu.HardwareType == Hardware.HardwareType.GpuAmd:
129+
amd_gpus += 1
130+
elif gpu.HardwareType == Hardware.HardwareType.GpuIntel:
131+
intel_gpus += 1
132+
elif gpu.HardwareType == Hardware.HardwareType.GpuNvidia:
133+
nvidia_gpus += 1
134+
135+
if nvidia_gpus >= 1:
136+
# One (or more) Nvidia GPU: use first available for stats
137+
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuNvidia).Name
138+
elif amd_gpus == 1:
139+
# No Nvidia GPU, only one AMD GPU: use it
140+
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuAmd).Name
141+
elif amd_gpus > 1:
142+
# No Nvidia GPU, several AMD GPUs found: try to use the real GPU but not the APU integrated in CPU
143+
for gpu in hw_gpus:
144+
if gpu.HardwareType == Hardware.HardwareType.GpuAmd:
145+
for sensor in gpu.Sensors:
146+
if sensor.SensorType == Hardware.SensorType.Load and str(sensor.Name).startswith("GPU Core"):
147+
# Found load sensor for this GPU: assume it is main GPU and use it for stats
148+
gpu_to_use = gpu.Name
149+
else:
150+
# No AMD or Nvidia GPU: there are several Intel GPUs, use first available for stats
151+
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuIntel).Name
152+
153+
if gpu_to_use:
154+
logger.debug("This GPU will be used for stats: %s" % gpu_to_use)
155+
else:
156+
logger.debug("No supported GPU found (no GPU with load sensor)")
157+
158+
return gpu_to_use
159+
160+
98161
def get_net_interface_and_update(if_name: str) -> Hardware.Hardware:
99162
for hardware in handle.Hardware:
100163
if hardware.HardwareType == Hardware.HardwareType.Network and hardware.Name == if_name:
@@ -173,13 +236,15 @@ def temperature() -> float:
173236

174237

175238
class Gpu(sensors.Gpu):
176-
@staticmethod
177-
def stats() -> Tuple[float, float, float, float]: # load (%) / used mem (%) / used mem (Mb) / temp (°C)
178-
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuAmd)
239+
gpu_name = ""
240+
241+
@classmethod
242+
def stats(cls) -> Tuple[float, float, float, float]: # load (%) / used mem (%) / used mem (Mb) / temp (°C)
243+
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuAmd, cls.gpu_name)
179244
if gpu_to_use is None:
180-
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuNvidia)
245+
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuNvidia, cls.gpu_name)
181246
if gpu_to_use is None:
182-
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuIntel)
247+
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuIntel, cls.gpu_name)
183248
if gpu_to_use is None:
184249
# GPU not supported
185250
return math.nan, math.nan, math.nan, math.nan
@@ -206,17 +271,10 @@ def stats() -> Tuple[float, float, float, float]: # load (%) / used mem (%) / u
206271

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

209-
@staticmethod
210-
def is_available() -> bool:
211-
found_amd = (get_hw_and_update(Hardware.HardwareType.GpuAmd) is not None)
212-
found_nvidia = (get_hw_and_update(Hardware.HardwareType.GpuNvidia) is not None)
213-
found_intel = (get_hw_and_update(Hardware.HardwareType.GpuIntel) is not None)
214-
215-
if (found_amd and (found_nvidia or found_intel)) or (found_nvidia and found_intel):
216-
logger.info(
217-
"Found multiple GPUs on your system. Will use dedicated GPU (AMD/Nvidia) for stats if possible.")
218-
219-
return found_amd or found_nvidia or found_intel
274+
@classmethod
275+
def is_available(cls) -> bool:
276+
cls.gpu_name = get_gpu_name()
277+
return bool(cls.gpu_name)
220278

221279

222280
class Memory(sensors.Memory):

0 commit comments

Comments
 (0)