方法简介
**nvidia-smi**简称NVSMI,提供监控GPU使用情况和更改GPU状态的功能,是一个跨平台工具,它支持所有标准的NVIDIA驱动程序支持的Linux发行版以及从WindowsServer 2008 R2开始的64位的系统。该工具是N卡驱动附带的,只要安装好驱动后就会有它
调用nvidia-smi,将输出存至本地,解析并获取当前GPU状态信息,使用Flask模板传入Echarts来可视化。
一些知识
实现
- 首先第一步是构造函数调用 nvidia-smi,存储命令输出结果,构造函数:
1 | # 每次调用,更新状态,加到存储,对此函数定时调用【一小时一调用】 |
然后构造函数定时调用,即定时更新状态并存储
1
2
3
4
5
6
7
8
9
10
11def re_exe(cmd, inc = 3600):
while True:
#os.system(cmd)
cmd()
time.sleep(inc)
...
if __name__ == '__main__':
#data = get_data_util('info.xml', 'gpu_util')
#print(data)
re_exe(ontime_check_util, 3600)构造函数解析GPU状态信息——info.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#GPU资源利用率
def get_data_util(xml_fname, util_name):
data_util = []
xmlfilepath = os.path.abspath( xml_fname )
print ("xml path:", xmlfilepath)
# Get the document object
domobj = xmldom.parse(xml_fname)
print("xmldom.parse:", type(domobj))
# Get the element object
elementobj = domobj.documentElement
print ("domobj.documentElement:", type(elementobj))
#1========================Get gpu_util==========================================
subElementObj1 = elementobj.getElementsByTagName( util_name )
for i in range(len(subElementObj1)):
#print ("subElementObj1[i]:", type(subElementObj1[i]))
data_util.append(int(str(subElementObj1[i].firstChild.data)[:-1])) #Displays data between tag pairs
print(util_name,data_util)
avg_data_util = sum(data_util)/len(data_util)
highest_data_util = max(data_util)
#return avg_gpu_util
return highest_data_util,avg_data_util,data_util调用解析函数,将结果加入存储(csv表格)。csv表格记存储了各个时间的状态信息。
1
2
3
4
5
6
7
8
9
10# 获取数据,更新存储
def add_util():
data = pd.DataFrame(columns=['gpu_util', 'time'])
#data = pd.read_csv('gpu.csv')
highest_data_util,avg_data_util,data_util = get_data_util('info.xml', 'gpu_util') # 若想获取内存信息,第二参数改为'memory_util'即可
data['gpu_util'] = [highest_data_util]
t = time.gmtime()
t = time.strftime("%Y/%m/%d:%H",t)
data['time'] = [t]
data.to_csv('gpu.csv', mode='a', header=False, index=None)构建函数将值传入Flask模板,用于Echarts图表展示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class show_gpu_utils:
def __init__(self,g,t):
self.gpu_utils = g
self.times = t
#for echarts
def gpu_utils_echarts():
data = pd.read_csv('gpu.csv', encoding='utf-8')
# ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
# [50.0, 55, 60, 54, 52, 61, 58, 54, 50, 49, 54, 60]
gpu_utils = list(data['gpu_utils'])
times = list(data['time'].apply(lambda x: int(x.split(':')[-1])))
highest_data_util = memory_gpu_util()
return show_gpu_utils(gpu_utils, times), str(highest_data_util)+' %'
Flask调用
1
2
3
4
def echarts1():
infos,now = GPU.gpu_utils_echarts()
return render_template('echarts1.html', infos=[infos], now=now)
结果展示
折线图为近期GPU负载占比记录,右上角为当前GPU负载占比
以下提供一些样例下载:
PS
- 若在Ubuntu里使用脚本执行
os.system(' xxx ')
命令,得先加一个cd命令进入工作台,因为os.system(‘ xxx ‘)命令在Ubuntu内等于重新开一个Shell窗口。
比如之前做了一个数据一键生成和一键训练的,核心语句如下:
1 | # Generate Data |
- 还有一点,若函数脚本所在文件夹是通过
sys.append(os.getcwd() + 'xxx/')
这样的方式import的,或者使用Python命令执行子目录的脚本 ,则脚本的工作台仍在根目录,举个栗子:上面的python ./train/generate.py
执行后shell仍在根目录,并不在train/
文件夹,因此train.py
内所有相对目录得加上./train/
,表示是train/
子目录下的文件.