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+
98163def 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
175240class 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
222283class Memory (sensors .Memory ):
0 commit comments