multiprocessing 充分利用cpu多核
一般情况下cpu密集使用进程池,IO密集使用线程池。python下想要充分利用多核CPU,就用多进程。
Process 类
Process 类用来描述一个进程对象。创建子进程的时候,只需要传入一个执行函数和函数的参数即可完成 Process 示例的创建。
star() 方法启动进程,
join() 方法实现进程间的同步,等待所有进程退出。
close() 用来阻止多余的进程涌入进程池 Pool 造成进程阻塞。
multiprocessing.Process(group=None, target=None, name=None, args=(), kwargs={}, *, daemon=None)
group: 线程组,目前还没有实现,库引用中提示必须是None;
target 是函数名字,需要调用的函数
args 函数需要的参数,以 tuple 的形式传入
实例方法:
is_alive():返回进程是否在运行。
join([timeout]):阻塞当前上下文环境的进程程,直到调用此方法的进程终止或到达指定的timeout(可选参数)。
start():进程准备就绪,等待CPU调度
run():strat()调用run方法,如果实例进程时未制定传入target,这star执行t默认run()方法。
terminate():不管任务是否完成,立即停止工作进程
属性:
authkey
daemon:和线程的setDeamon功能一样
exitcode(进程在运行时为None、如果为–N,表示被信号N结束)
name:进程名字。
pid:进程号。
列子一:
import multiprocessing
import os
def run_proc(name):print('Child process {0} {1} Running'.format(name, os.getpid()))if __name__ == '__main__':print('Parent process {0} is Running'.format(os.getpid()))for i in range(5):
p= multiprocessing.Process(target=run_proc, args=(str(i),))print('process start')
p.start()
p.join()print('Process close')[python@master test]$ python3 a.py
Parent process12665 isRunning
process start
process start
process start
Child process0 12666Running
process start
process start
Child process2 12668Running
Child process1 12667Running
Child process3 12669Running
Child process4 12670Running
Processclose
列子二:
#coding=utf-8import multiprocessing
def do(n) :
name=multiprocessing.current_process().nameprint(name,'starting')print("worker ", n)if __name__ == '__main__':for i in range(5) :
p= multiprocessing.Process(target=do, args=(i,))
p.start()
p.join()print ("Process end.")[python@master test]$ python3 b.py
Process-1starting
worker0Processend.
Process-2starting
worker1Processend.
Process-3starting
worker2Processend.
Process-4starting
worker3Processend.
Process-5starting
worker4Processend.
Pool类
进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。进程池设置最好等于CPU核心数量
构造方法:
Pool([processes[, initializer[, initargs[, maxtasksperchild[, context]]]]])
processes :使用的工作进程的数量,如果processes是None那么使用 os.cpu_count()返回的数量。
initializer: 如果initializer是None,那么每一个工作进程在开始的时候会调用initializer(*initargs)。
maxtasksperchild:工作进程退出之前可以完成的任务数,完成后用一个新的工作进程来替代原进程,来让闲置的资源被释放。maxtasksperchild默认是None,意味着只要Pool存在工作进程就会一直存活。
context: 用在制定工作进程启动时的上下文,一般使用 multiprocessing.Pool() 或者一个context对象的Pool()方法来创建一个池,两种方法都适当的设置了context
实例方法:
apply(func[, args[, kwds]]):同步进程池
apply_async(func[, args[, kwds[, callback[, error_callback]]]]) :异步进程池
close() : 关闭进程池,阻止更多的任务提交到pool,待任务完成后,工作进程会退出。
terminate() : 结束工作进程,不在处理未完成的任务
join() : wait工作线程的退出,在调用join()前,必须调用close() or terminate()。这样是因为被终止的进程需要被父进程调用wait(join等价与wait),否则进程会成为僵尸进程。
pool.join()必须使用在pool.close()或者pool.terminate()之后。其中close()跟terminate()的区别在于:
close()会等待池中的worker进程执行结束再关闭pool,而terminate()则是直接关闭。
异步进程池
#每次循环将会用空闲出来的子进程去调用目录--异步
#不等待只要进程池的位置空出来就立刻补上
# coding:utf-8
frommultiprocessing import Pool
import time
def Foo(i):
time.sleep(2)return i + 100def Bar(arg):print("callback"+str(arg))if __name__ == '__main__':
t_start=time.time()
pool= Pool(5)for i in range(10):
pool.apply_async(func=Foo, args=(i,), callback=Bar)#维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去
pool.close()
pool.join() # 进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。
pool.terminate()
t_end=time.time()
t=t_end-t_startprint ('the program time is :%s' %t)[python@master test]$ python3 c.py
callback100
callback103
callback101
callback102
callback104
callback107
callback106
callback109
callback105
callback108
the program timeis :4.0822553634643555
同步进程池
#阻塞式的请求 自加阻塞 顺序结构
#必须要在进程池中没有进程的的时候 才会有新进程进入进程池
# -*- coding:utf-8 -*-
frommultiprocessing import Process, Pool
import time
def Foo(i):
time.sleep(1)print (i + 100)if __name__ == '__main__':
t_start=time.time()
pool= Pool(5) #定义一个进程池,最大的进程数量for i in range(10):
pool.apply(Foo, (i,))
pool.close()
pool.join() # 进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。
t_end=time.time()
t=t_end-t_startprint('the program time is :%s' %t)[python@master test]$ python3 d.py100
101
102
103
104
105
106
107
108
109the program timeis :10.224181175231934
正确使用get()方法获取结果
# coding:utf-8
frommultiprocessing import Pool
import time
def Foo(i):
time.sleep(2)return i + 100def Bar(arg):print('callback'+str(arg))if __name__ == '__main__':
res_list=[]t_start=time.time()
pool= Pool(5)for i in range(10):
res= pool.apply_async(func=Foo, args=(i,), callback=Bar)#维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去
res_list.append(res)
pool.close()
pool.join() # 进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。for res inres_list:print(res.get())
pool.terminate()
t_end=time.time()
t=t_end-t_startprint ('the program time is :%s' %t)[python@master test]$ python3 e.py
callback101
callback100
callback102
callback104
callback103
callback105
callback109
callback106
callback107
callback108100
101
102
103
104
105
106
107
108
109the program timeis :4.145965099334717
进程数据共享
进程各自持有一份数据,默认无法共享数据
# coding:utf-8
frommultiprocessing import Process
li= []def foo(i):
li.append(i)print ('say hi', li)if __name__ == '__main__':for i in range(10):
p= Process(target=foo, args=(i,))
p.start()print ('ending', li)[python@master test]$ python3 a.py
say hi[0]say hi[2]say hi[3]say hi[5]say hi[1]say hi[6]ending[]say hi[7]say hi[4]say hi[9]say hi[8]
方法一(使用Array):
frommultiprocessing import Process, Array
def f(a):for i in range(len(a)):
a[i] = -a[i]
if __name__ == '__main__':
arr= Array('i', range(10))
p= Process(target=f, args=(arr,))
p.start()
p.join()print(arr[:])[python@master test]$ python3 b.py[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
方法二(使用Manager):
Manager()返回的manager提供list, dict, Namespace, Lock, RLock, Semaphore, BoundedSemaphore, Condition, Event, Barrier, Queue, Value and Array类型的支持。
frommultiprocessing import Process, Manager
def f(d, l):
d[1] = '1'd['2'] = 2d[0.25] =None
l.reverse()if __name__ == '__main__':with Manager() asmanager:
d=manager.dict()
l= manager.list(range(10))
p= Process(target=f, args=(d, l))
p.start()
p.join()print(d)print(l)[python@master test]$ python3 c.py
{1: '1', '2': 2, 0.25: None}[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
使用多个进程池:
#coding: utf-8import multiprocessing
import os, time, random
def Lee():print ("\nRun task Lee-%s" %(os.getpid())) #os.getpid()获取当前的进程的ID
start=time.time()
time.sleep(random.random()* 10) #random.random()随机生成0-1之间的小数end =time.time()print ('Task Lee, runs %0.2f seconds.' %(end -start))
def Marlon():print ("\nRun task Marlon-%s" %(os.getpid()))
start=time.time()
time.sleep(random.random()* 40)end=time.time()print ('Task Marlon runs %0.2f seconds.' %(end -start))
def Allen():print ("\nRun task Allen-%s" %(os.getpid()))
start=time.time()
time.sleep(random.random()* 30)end =time.time()print ('Task Allen runs %0.2f seconds.' %(end -start))
def Frank():print ("\nRun task Frank-%s" %(os.getpid()))
start=time.time()
time.sleep(random.random()* 20)end =time.time()print ('Task Frank runs %0.2f seconds.' %(end -start))if __name__=='__main__':
function_list= [Lee, Marlon, Allen, Frank]
print ("parent process %s" %(os.getpid()))
pool=multiprocessing.Pool(4)for func infunction_list:
pool.apply_async(func) #Pool执行函数,apply执行函数,当有一个进程执行完毕后,会添加一个新的进程到pool中print ('Waiting for all subprocesses done...')
pool.close()
pool.join() #调用join之前,一定要先调用close() 函数,否则会出错, close()执行后不会有新的进程加入到pool,join函数等待素有子进程结束print ('All subprocesses done.')[python@master test]$ python3 e.py
parent process20714Waitingfor allsubprocesses done...
Run task Lee-20715Run task Marlon-20716Run task Allen-20718Run task Frank-20717Task Lee, runs3.18seconds.
Task Frank runs11.47seconds.
Task Allen runs23.24seconds.
Task Marlon runs38.09seconds.All subprocesses done.