【python】详解multiprocessing多进程-process模块(一)
【python】详解multiprocessing多进程-Pool进程池模块(二)
【python】详解multiprocessing多进程-Queue、Pipe进程间通信(三)
【python】详解multiprocessing多进程-Lock、Rlock进程同步(四)
【python】详解multiprocessing多进程-总结(五)
由于GIL的存在,python中的多线程其实并不是真正的多线程,如果想要充分地使用多核CPU的资源,在python中大部分情况需要使用多进程。Python提供了非常好用的多进程包multiprocessing,只需要定义一个函数,Python会完成其他所有事情。借助这个包,可以轻松完成从单进程到并发执行的转换。multiprocessing支持子进程、通信和共享数据、执行不同形式的同步,提供了Process、Queue、Pipe、Lock等组件。
multiprocessing包是Python中的多进程管理包。与threading.Thread类似,它可以利用multiprocessing.Process对象来创建一个进程。该进程可以运行在Python程序内部编写的函数。该Process对象与Thread对象的用法相同,也有start(), run(), join()的方法。此外multiprocessing包中也有Lock/Event/Semaphore/Condition类 (这些对象可以像多线程那样,通过参数传递给各个进程),用以同步进程,其用法与threading包中的同名类一致。所以,multiprocessing的很大一部份与threading使用同一套API,只不过换到了多进程的情境。
但在使用这些共享API的时候,我们要注意以下几点:
multiprocessing提供了threading包中没有的IPC(比如Pipe和Queue),效率上更高。应优先考虑Pipe和Queue,避免使用Lock/Event/Semaphore/Condition等同步方式 (因为它们占据的不是用户进程的资源)。
多进程应该避免共享资源。在多线程中,我们可以比较容易地共享资源,比如使用全局变量或者传递参数。在多进程情况下,由于每个进程有自己独立的内存空间,以上方法并不合适。此时我们可以通过共享内存和Manager的方法来共享资源。但这样做提高了程序的复杂度,并因为同步的需要而降低了程序的效率。
Process.PID中保存有PID,如果进程还没有start(),则PID为None。
window系统下,需要注意的是要想启动一个子进程,必须加上那句if name == “main”,进程相关的要写在这句下面。
from multiprocessing import Process
def foo(i):
print ('say hi', i)
if __name__ == '__main__':
for i in range(10):
p = Process(target=foo, args=(i,))
p.start()
------------------------------------------
say hi 0
say hi 1
say hi 2
say hi 3
say hi 4
say hi 5
say hi 6
say hi 7
say hi 8
say hi 9
from multiprocessing import Process
import time
class MyProcess(Process):
def __init__(self, arg):
super(MyProcess, self).__init__()
self.arg = arg
def run(self):
print('say hi', self.arg)
time.sleep(1)
if __name__ == '__main__':
for i in range(10):
p = MyProcess(i)
p.start()
Process([group [, target [, name [, args [, kwargs]]]]])
from multiprocessing import Process
def foo(i):
print('say hi', i)
if __name__ == '__main__':
for i in range(10):
p = Process(target=foo, args=(i,))
p.start()
----------------------------------------------
say hi 0
say hi 1
say hi 2
say hi 3
say hi 4
say hi 5
say hi 6
say hi 7
say hi 8
say hi 9
from multiprocessing import Process
import time
def foo(i):
time.sleep(1)
print('say hi', i)
time.sleep(1)
if __name__ == '__main__':
p_list=[]
for i in range(10):
p = Process(target=foo, args=(i,))
p.daemon=True
p_list.append(p)
for p in p_list:
p.start()
for p in p_list:
p.join()
print('main process end')
------------------------------------------------
say hi 0
say hi 1
say hi 2
say hi 3
say hi 4
say hi 5
say hi 6
say hi 7
say hi 8
say hi 9
main process end
进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进进程,那么程序就会等待,直到进程池中有可用进程为止。进程池设置最好等于CPU核心数量
Pool([processes[, initializer[, initargs[, maxtasksperchild[, context]]]]])
pool.join()必须使用在pool.close()或者pool.terminate()之后。其中close()跟terminate()的区别在于close()会等待池中的worker进程执行结束再关闭pool,而terminate()则是直接关闭。
from multiprocessing import Pool
import time
def Foo(i):
time.sleep(2)
return i + 100
def Bar(arg):
print(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_start
print('the program time is :%s' %t)
from multiprocessing 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_start
print('the program time is :%s' %t)
from multiprocessing import Process, Pool
import time
def Foo(i):
time.sleep(1)
return i+100
def Bar(arg):
return arg
if __name__ == '__main__':
t_start=time.time()
pool = Pool(5)
for i in range(10):
res = pool.apply_async(func=Foo, args=(i,), callback=Bar)#维持执行的进程总数为processes,当一个进程执行完毕后会添加新的进程进去
print(res.get())
pool.close()
pool.join() # 进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。
pool.terminate()
t_end=time.time()
t=t_end-t_start
print('the program time is :%s' %t)
----------------------------------------------------------
100
101
102
103
104
105
106
107
108
109
the program time is :10.273606538772583
from multiprocessing import Pool
import time
def Foo(i):
time.sleep(2)
return i + 100
def Bar(arg):
return 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)
res_list.append(res)
pool.close()
pool.join()
for res in res_list:
print(res.get())
t_end=time.time()
t=t_end-t_start
print('the program time is :%s' %t)
---------------------------------------------------------------
100
101
102
103
104
105
106
107
108
109
the program time is :4.311059236526489
from multiprocessing 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)
Array(‘i’, range(10))中的‘i’参数C语言中的类型:
‘c’: ctypes.c_char ‘u’: ctypes.c_wchar ‘b’: ctypes.c_byte ‘B’: ctypes.c_ubyte
‘h’: ctypes.c_short ‘H’: ctypes.c_ushort ‘i’: ctypes.c_int ‘I’: ctypes.c_uint
‘l’: ctypes.c_long, ‘L’: ctypes.c_ulong ‘f’: ctypes.c_float ‘d’: ctypes.c_double
from multiprocessing 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[:])
--------------------------------------------------
[0, -1, -2, -3, -4, -5, -6, -7, -8, -9]
from multiprocessing import Process, Manager
def f(d, l):
d[1] = '1'
d['2'] = 2
d[0.25] = None
l.reverse()
if __name__ == '__main__':
with Manager() as manager:
d = manager.dict()
l = manager.list(range(10))
p = Process(target=f, args=(d, l))
p.start()
p.join()
print(d)
print(l)
-------------------------------------------------------------
{1: '1', '2': 2, 0.25: None}
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]