多线程,实现对CPU、GPU状态的监控
文章目录
- 一、获取代码运行时间
- 二、对CPU、GPU状态的监控
- 三、多线程:threading模块的Thread类
- a、核心要点
- b、第一种方法添加子线程:实例化Thread类
- c、第二种方法添加子线程:自定义Thread的子类,重写run方法
一、获取代码运行时间
(参考链接)
import time
start=time.time()
#中间写上代码块
end=time.time()
print('Running time: %s Seconds'%(end-start))#单位是s
二、对CPU、GPU状态的监控
1、命令行:nvidia-smi,其中PID(Process Identification)指进程识别号。(关闭指定GPU进程用:kill -9 PID1 PID2 PIDn)
2、命令行:gpustat(相比于nvidia-smi显示更简洁),gpustat --help查看更多用法上述两条命令配合watch命令(watch --help查看用法)都可以实时显示GUP运行状态,如watch -d -n 1 nvidia-smi/gpustat
3、通过以下代码(参考链接)
import GPUtil
import time
import psutil
stopped_num = 10000000 #设置一个最大获取次数,防止记录文本爆炸
delay = 10 #采样信息时间间隔
Gpus = GPUtil.getGPUs()
def get_gpu_info():
gpulist = []
GPUtil.showUtilization()
# 获取多个GPU的信息,存在列表里
for gpu in Gpus:
print('gpu.id:', gpu.id)
print('GPU总量:', gpu.memoryTotal)
print('GPU使用量:', gpu.memoryUsed)
print('gpu使用占比:', gpu.memoryUtil * 100)
# 按GPU逐个添加信息
gpulist.append([ gpu.id, gpu.memoryTotal, gpu.memoryUsed,gpu.memoryUtil * 100])
return gpulist
def get_cpu_info():
''' :return:
memtotal: 总内存
memfree: 空闲内存
memused: Linux: total - free,已使用内存
mempercent: 已使用内存占比
cpu: 各个CPU使用占比
'''
mem = psutil.virtual_memory()
memtotal = mem.total
memfree = mem.free
mempercent = mem.percent
memused = mem.used
cpu = psutil.cpu_percent(percpu=True)
return memtotal, memfree, memused, mempercent, cpu
# 主函数
def main():
times = 0
while True:
# 最大循环次数
if times < stopped_num:
# 打印当前时间
time.strftime('%Y-%m-%d %H:%M:%S',time.localtime(time.time()))
# 获取CPU信息
cpu_info = get_cpu_info()
# 获取GPU信息
gpu_info = get_gpu_info()
# 添加时间间隙
print(cpu_info)
print(gpu_info,'\n')
time.sleep(delay)
times += 1
else:
break
if __name__ == '__main__':
main()
三、多线程:threading模块的Thread类
a、核心要点
1、程序运行时默认就是在主线程上
2、通过实例化Thread类可以添加子线程
,不同的线程同时处理不同的任务,这就是多线程编程
3、有两种方法
可以添加子线程,如下:
b、第一种方法添加子线程:实例化Thread类
实例化Thread类。通过该实例对象的start()方法启动线程,线程抛出异常或执行完时自动退出。
(参考链接)
(1)三条知识点:threading库中的Thread类的定义
,threading的属性和方法
,Thread类的实例对象的属性和方法
1、threading库中的Thread类的定义
class threading.Thread(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)
参数名及含义:
target 线程调用的对象,就是目标函数
name 为线程起一个名字(线程的名字)
args 为目标函数传递实参,元组
kwargs 为目标函数传递关键字参数,字典
2、threading的属性和方法:
threading.current_thread() 返回当前线程对象
threading.current_thread().ident 返回当前线程的id
threading.getident() 返回当前线程的ID,非0整数
threading.main_thread() 返回主线程(main线程)对象
threading.active_count() 返回当前启动的且还未结束的线程个数
threading.enumerate() 返回当前启动的且还未结束的线程列表
3、Thread类的实例对象的属性和方法
Thread.name 线程的名字,一个标识符,线程的名称可以重名。getName(),setName()获取、设置这个名词
Thread.ident 线程ID,是个非0的整数。线程启动后才会有ID,否则为None。线程退出,此时Id依旧可以访问。此ID会被系统重复使用
Thread.is_alive() 返回线程是否或者
(2)案例:通过实例化Thread类来添加子线程注意:
下面例子中,主进程、子线程t1、子线程t2
同时在运行,所以可以看见运行结果在交替输出。
import threading
import time
def worker1():
print("子线程1开始")
time.sleep(5)
print("过了5s后,子线程1结束")
def worker2(x,y):
print("{}+{}={}".format(x,y,x+y),threading.current_thread())
print(threading.current_thread().ident)
print(threading.get_ident())
print(threading.main_thread())
print(threading.active_count())
print(threading.enumerate(), len(threading.enumerate()))
t1 = threading.Thread(target=worker1,name="t1") #实例化Thread类,创建第一个子线程
t1.start() #启动第一个子线程
t2 = threading.Thread(target=worker2,name="t2",args=(3,),kwargs={"y":15})#实例化Thread类,创建第二个子线程
t2.start()#启动第二个子线程
print(t2.name, t2.ident, t2.is_alive())
"""运行结果:
子线程1开始
3+15=18 <Thread(t2, started 140569273763584)>
注意输出的位置 t2 140569273763584 True
140569273763584
140569273763584
<_MainThread(MainThread, stopped 140569293787520)>
3
[<_MainThread(MainThread, stopped 140569293787520)>, <Thread(t1, started 140569282156288)>, <Thread(t2, started 140569273763584)>] 3
过了5s后,子线程1结束
"""
c、第二种方法添加子线程:自定义Thread的子类,重写run方法
通过继承Thread类来自定义一个Thread的子类,重写它的run方法。实例化该Thread子类,通过该对象的start()方法运行。
(启动线程使用start()方法,该方法会自动调用run()方法,而run()方法用来运行函数)(参考链接)
import threading
import time
class worker1(threading.Thread):
def run(self):
print("子线程1开始")
time.sleep(5)
print("过了5s后,子线程1结束")
class worker2(threading.Thread):
def run(self):
print(threading.current_thread().ident)
print(threading.get_ident())
print(threading.main_thread())
print(threading.active_count())
print(threading.enumerate(), len(threading.enumerate()))
t1=worker1(name='t1')
t1.start()
t2=worker2(name='t2')
t2.start()
"""运行结果:
子线程1开始
140396349708032
140396349708032
<_MainThread(MainThread, started 140396369731968)>
3
[<_MainThread(MainThread, started 140396369731968)>, <worker1(t1, started 140396358100736)>, <worker2(t2, started 140396349708032)>] 3
过了5s后,子线程1结束
"""