Skip to content

Commit 04deaf4

Browse files
authored
Merge pull request #214 from mathoudebine/fix/get-best-gpu-for-stats
Detect and handle multiple GPUs better
2 parents 2ec2d36 + 45f5852 commit 04deaf4

File tree

3 files changed

+82
-20
lines changed

3 files changed

+82
-20
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/lcd/lcd_comm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def openSerial(self):
7676
if self.com_port == 'AUTO':
7777
lcd_com_port = self.auto_detect_com_port()
7878
if not lcd_com_port:
79-
logger.error("Cannot find COM port automatically, please set it manually in config.yaml")
79+
logger.error("Cannot find COM port automatically, please run Configuration again and select COM port manually")
8080
try:
8181
sys.exit(0)
8282
except:

library/sensors/sensors_librehardwaremonitor.py

Lines changed: 80 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -87,14 +87,79 @@
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.warning("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+
amd_gpus = 0
119+
intel_gpus = 0
120+
nvidia_gpus = 0
121+
122+
gpu_to_use = ""
123+
124+
# Count GPUs by manufacturer
125+
for gpu in hw_gpus:
126+
if gpu.HardwareType == Hardware.HardwareType.GpuAmd:
127+
amd_gpus += 1
128+
elif gpu.HardwareType == Hardware.HardwareType.GpuIntel:
129+
intel_gpus += 1
130+
elif gpu.HardwareType == Hardware.HardwareType.GpuNvidia:
131+
nvidia_gpus += 1
132+
133+
logger.warning(
134+
"Found %d GPUs on your system (%d AMD / %d Nvidia / %d Intel). Auto identify which GPU to use." % (
135+
len(hw_gpus), amd_gpus, nvidia_gpus, intel_gpus))
136+
137+
if nvidia_gpus >= 1:
138+
# One (or more) Nvidia GPU: use first available for stats
139+
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuNvidia).Name
140+
elif amd_gpus == 1:
141+
# No Nvidia GPU, only one AMD GPU: use it
142+
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuAmd).Name
143+
elif amd_gpus > 1:
144+
# No Nvidia GPU, several AMD GPUs found: try to use the real GPU but not the APU integrated in CPU
145+
for gpu in hw_gpus:
146+
if gpu.HardwareType == Hardware.HardwareType.GpuAmd:
147+
for sensor in gpu.Sensors:
148+
if sensor.SensorType == Hardware.SensorType.Load and str(sensor.Name).startswith("GPU Core"):
149+
# Found load sensor for this GPU: assume it is main GPU and use it for stats
150+
gpu_to_use = gpu.Name
151+
else:
152+
# No AMD or Nvidia GPU: there are several Intel GPUs, use first available for stats
153+
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuIntel).Name
154+
155+
if gpu_to_use:
156+
logger.debug("This GPU will be used for stats: %s" % gpu_to_use)
157+
else:
158+
logger.warning("No supported GPU found (no GPU with load sensor)")
159+
160+
return gpu_to_use
161+
162+
98163
def get_net_interface_and_update(if_name: str) -> Hardware.Hardware:
99164
for hardware in handle.Hardware:
100165
if hardware.HardwareType == Hardware.HardwareType.Network and hardware.Name == if_name:
@@ -173,13 +238,16 @@ def temperature() -> float:
173238

174239

175240
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)
241+
# GPU to use is detected once, and its name is saved for future sensors readings
242+
gpu_name = ""
243+
244+
@classmethod
245+
def stats(cls) -> Tuple[float, float, float, float]: # load (%) / used mem (%) / used mem (Mb) / temp (°C)
246+
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuAmd, cls.gpu_name)
179247
if gpu_to_use is None:
180-
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuNvidia)
248+
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuNvidia, cls.gpu_name)
181249
if gpu_to_use is None:
182-
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuIntel)
250+
gpu_to_use = get_hw_and_update(Hardware.HardwareType.GpuIntel, cls.gpu_name)
183251
if gpu_to_use is None:
184252
# GPU not supported
185253
return math.nan, math.nan, math.nan, math.nan
@@ -206,17 +274,10 @@ def stats() -> Tuple[float, float, float, float]: # load (%) / used mem (%) / u
206274

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

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
277+
@classmethod
278+
def is_available(cls) -> bool:
279+
cls.gpu_name = get_gpu_name()
280+
return bool(cls.gpu_name)
220281

221282

222283
class Memory(sensors.Memory):

0 commit comments

Comments
 (0)