30
30
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
31
31
# SOFTWARE.
32
32
33
+ import encodings
34
+ import logging
33
35
from subprocess import Popen , PIPE
34
36
from distutils import spawn
35
37
import os
@@ -67,19 +69,29 @@ def safeFloatCast(strNumber):
67
69
68
70
def getGPUs ():
69
71
if platform .system () == "Windows" :
70
- # If the platform is Windows and nvidia-smi
71
- # could not be found from the environment path,
72
+ # If the platform is Windows and nvidia-smi
73
+ # could not be found from the environment path,
72
74
# try to find it from system drive with default installation path
73
75
nvidia_smi = spawn .find_executable ('nvidia-smi' )
74
76
if nvidia_smi is None :
75
77
nvidia_smi = "%s\\ Program Files\\ NVIDIA Corporation\\ NVSMI\\ nvidia-smi.exe" % os .environ ['systemdrive' ]
76
78
else :
77
79
nvidia_smi = "nvidia-smi"
78
-
80
+
79
81
# Get ID, processing and memory utilization for all GPUs
80
82
try :
83
+ output = ""
84
+ output_stderr = ""
81
85
p = Popen ([nvidia_smi ,"--query-gpu=index,uuid,utilization.gpu,memory.total,memory.used,memory.free,driver_version,name,gpu_serial,display_active,display_mode,temperature.gpu" , "--format=csv,noheader,nounits" ], stdout = PIPE )
82
- stdout , stderror = p .communicate ()
86
+ stdout , stderr = p .communicate ()
87
+ if stdout :
88
+ output = stdout .decode (encodings .utf_8 .getregentry ().name )
89
+ if stderr :
90
+ output_stderr = stderr .decode (encodings .utf_8 .getregentry ().name )
91
+ if p .returncode != 0 :
92
+ nvidia_smi_error_message = f"{ output } { output_stderr } " .strip ()
93
+ logging .error ("%s error: %s" , nvidia_smi , nvidia_smi_error_message )
94
+ return []
83
95
except :
84
96
return []
85
97
output = stdout .decode ('UTF-8' )
@@ -227,7 +239,7 @@ def showUtilization(all=False, attrList=None, useOldCode=False):
227
239
{'attr' :'memoryFree' ,'name' :'Memory free' ,'suffix' :'MB' ,'precision' :0 }],
228
240
[{'attr' :'display_mode' ,'name' :'Display mode' },
229
241
{'attr' :'display_active' ,'name' :'Display active' }]]
230
-
242
+
231
243
else :
232
244
if (useOldCode ):
233
245
print (' ID GPU MEM' )
@@ -240,7 +252,7 @@ def showUtilization(all=False, attrList=None, useOldCode=False):
240
252
{'attr' :'load' ,'name' :'GPU' ,'suffix' :'%' ,'transform' : lambda x : x * 100 ,'precision' :0 },
241
253
{'attr' :'memoryUtil' ,'name' :'MEM' ,'suffix' :'%' ,'transform' : lambda x : x * 100 ,'precision' :0 }],
242
254
]
243
-
255
+
244
256
if (not useOldCode ):
245
257
if (attrList is not None ):
246
258
headerString = ''
@@ -251,15 +263,15 @@ def showUtilization(all=False, attrList=None, useOldCode=False):
251
263
headerString = headerString + '| ' + attrDict ['name' ] + ' '
252
264
headerWidth = len (attrDict ['name' ])
253
265
minWidth = len (attrDict ['name' ])
254
-
266
+
255
267
attrPrecision = '.' + str (attrDict ['precision' ]) if ('precision' in attrDict .keys ()) else ''
256
268
attrSuffix = str (attrDict ['suffix' ]) if ('suffix' in attrDict .keys ()) else ''
257
269
attrTransform = attrDict ['transform' ] if ('transform' in attrDict .keys ()) else lambda x : x
258
270
for gpu in GPUs :
259
271
attr = getattr (gpu ,attrDict ['attr' ])
260
-
272
+
261
273
attr = attrTransform (attr )
262
-
274
+
263
275
if (isinstance (attr ,float )):
264
276
attrStr = ('{0:' + attrPrecision + 'f}' ).format (attr )
265
277
elif (isinstance (attr ,int )):
@@ -271,20 +283,20 @@ def showUtilization(all=False, attrList=None, useOldCode=False):
271
283
attrStr = attr .encode ('ascii' ,'ignore' )
272
284
else :
273
285
raise TypeError ('Unhandled object type (' + str (type (attr )) + ') for attribute \' ' + attrDict ['name' ] + '\' ' )
274
-
286
+
275
287
attrStr += attrSuffix
276
-
288
+
277
289
minWidth = max (minWidth ,len (attrStr ))
278
-
290
+
279
291
headerString += ' ' * max (0 ,minWidth - headerWidth )
280
-
292
+
281
293
minWidthStr = str (minWidth - len (attrSuffix ))
282
-
294
+
283
295
for gpuIdx ,gpu in enumerate (GPUs ):
284
296
attr = getattr (gpu ,attrDict ['attr' ])
285
-
297
+
286
298
attr = attrTransform (attr )
287
-
299
+
288
300
if (isinstance (attr ,float )):
289
301
attrStr = ('{0:' + minWidthStr + attrPrecision + 'f}' ).format (attr )
290
302
elif (isinstance (attr ,int )):
@@ -296,15 +308,15 @@ def showUtilization(all=False, attrList=None, useOldCode=False):
296
308
attrStr = ('{0:' + minWidthStr + 's}' ).format (attr .encode ('ascii' ,'ignore' ))
297
309
else :
298
310
raise TypeError ('Unhandled object type (' + str (type (attr )) + ') for attribute \' ' + attrDict ['name' ] + '\' ' )
299
-
311
+
300
312
attrStr += attrSuffix
301
-
313
+
302
314
GPUstrings [gpuIdx ] += '| ' + attrStr + ' '
303
-
315
+
304
316
headerString = headerString + '|'
305
317
for gpuIdx ,gpu in enumerate (GPUs ):
306
318
GPUstrings [gpuIdx ] += '|'
307
-
319
+
308
320
headerSpacingString = '-' * len (headerString )
309
321
print (headerString )
310
322
print (headerSpacingString )
0 commit comments