由于Python的全局解释器锁(GIL)的限制,每次只有一个线程在运行,这导致使用多线程在Python程序中并不能提高性能,只有在IO密集型任务中才稍稍有点用处。要想充分利用CPU资源,这个时候就得用多进程。
1,简单的使用
from multiprocessing import Process
import time
import os
def run(name):
while True:
time.sleep(2)
print("子进程ID号:%d,run:%s" % (os.getpid(), name)) # os.getpid()进程ID
if __name__ == "__main__":
print("父进程启动:%d" % os.getpid())
# 创建子进程
p = Process(target=run, args=("Ail",)) # target进程执行的任务, args传参数(元祖)
p.start() # 启动进程
while True:
print("死循环")
time.sleep(1)
# 输出结果
主进程启动:36684
死循环
死循环
死循环
子进程ID号:40228,run:Ail
死循环
父进程与子进程创建子进程一定要在主进程没有执行死循环的时候创建,不然子进程无法创建
2,启动大量的子进程可以用进程池批量创建子进程。
import random
from multiprocessing.pool import Pool
from time import sleep, time
import os
def run(name):
print("%s子进程开始,进程ID:%d" % (name, os.getpid()))
start = time()
sleep(random.choice([1, 2, 3, 4]))
end = time()
print("%s子进程结束,进程ID:%d。耗时0.2%f" % (name, os.getpid(), end-start))
if __name__ == "__main__":
print("父进程开始")
# 创建多个进程,表示可以同时执行的进程数量。默认大小是CPU的核心数
p = Pool(8)
for i in range(10):
# 创建进程,放入进程池统一管理
p.apply_async(run, args=(i,))
# 如果我们用的是进程池,在调用join()之前必须要先close(),并且在close()之 #后不能再继续往进程池添加新的进程
p.close()
# 进程池对象调用join,会等待进程吃中所有的子进程结束完毕再去结束父进程
p.join()
print("父进程结束。")
'#'输出结果
父进程开始
0子进程开始,进程ID:41380
1子进程开始,进程ID:44756
2子进程开始,进程ID:31936
3子进程开始,进程ID:32000
3子进程结束,进程ID:32000。耗时0.21.000601
4子进程开始,进程ID:32000
0子进程结束,进程ID:41380。耗时0.22.000833
5子进程开始,进程ID:41380
2子进程结束,进程ID:31936。耗时0.23.000310
1子进程结束,进程ID:44756。耗时0.24.000483
4子进程结束,进程ID:32000。耗时0.23.000789
5子进程结束,进程ID:41380。耗时0.23.000035
实例2,使用map
def CreateBaseGrids(df_T054_Grid, GridType, n):
process_number = mp.cpu_count()
pools = mp.Pool(process_number)
re_list=pools.map(train_fun,para_list)
pools.close()
pools.join()
return re_list
def train_fun(para):
re = do_something
return re
后记:
在工程开发中发现,当启动多进程时,内存消耗急剧增加,主要是因为使用mp启动多进程时,每个子进程都会fork父进程,这样如果父进程加载了大量数据,则每个子进程都会copy一份数据,内存消耗极大;
为了减少内存消耗,父进程最好不要加载大数据,可以将数据加载房子子进程里面。参考:https://www.cnblogs.com/shanguanghui/p/7677348.html 的介绍。
参考:https://www.cnblogs.com/hello-wei/p/10168544.html
https://www.jianshu.com/p/a5f10c152c20