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+
98161def 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
175238class 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
222280class Memory (sensors .Memory ):
0 commit comments