multiprocessing 是一个支持使用与 threading 模块类似的 API 来产生进程的包。 multiprocessing 包同时提供了本地和远程并发操作,通过使用子进程而非线程有效地绕过了全局解释器锁。 因此,multiprocessing 模块允许程序员充分利用给定机器上的多个处理器。 它在 Unix 和 Windows 上均可运行。
multiprocessing 模块还引入了在 threading 模块中没有的API。一个主要的例子就是 Pool 对象,它提供了一种快捷的方法,赋予函数并行化处理一系列输入值的能力,可以将输入数据分配给不同进程处理(数据并行)。下面的例子演示了在模块中定义此类函数的常见做法,以便子进程可以成功导入该模块。这个数据并行的基本例子使用了 Pool :
from multiprocessing import Pool
def f(x):
return x*x
if __name__ == '__main__':
with Pool(5) as p:
print(p.map(f, [1, 2, 3]))
将在标准输出中打印:
[1, 4, 9]
使用 Pool 实现多进程的步骤
Pool 类表示一个工作进程池。它具有允许以几种不同方式将任务分配到工作进程的方法。
第一步,创建任务函数。并行的目的也是为了能够更快的执行这个任务函数。例如
def func(x,y):
return x+y
第二步,调用 Pool 方法实例化一个进程池。例如通过下面的代码实例化一个最大进程数为4的进程池。
from multiprocessing import Pool
P = Pool(processes=4)
第三步,进程执行。几种常用方式
(1) map
如果进程任务有返回值,且返回值需要集中处理,则建议采用 map 的方式。但该方式 只允许向任务函数传递一个参数
。
此外,map 方式对应的子进程是排队执行的,实际非并行(阻塞的,即上一个子进程完成了才能进行下一个子进程;注意是单个子进程执行的,而不是按批执行的)
P.map(func, iterable, chunksize=None)
func : 任务函数
iterable : 迭代对象,每个进程依次取迭代对象的一个元素作为任务函数的参数
对于很长的迭代对象,可能消耗很多内存。可以指定 chunksize 以提升效率。该参数是将迭代对象分成几个块。
(2) starmap
如果子进程活动具有多个参数,则不能直接使用map方式,需采用starmap方式。同样的,starmap 也不是真正的并行,而是排队执行的。
def func(a, b): #starmap方法允许多个参数
return a
pool = multiprocessing.Pool()
result = pool.starmap(func, ((a0, b0), (a1, b1), ...)).get()
pool.close()
pool.join()
子进程活动func允许包含多个参数,也即iterable的每个元素也是iterable(其每个元素作为func的参数),返回结果组成的list。
(3) starmap_async
starmap_async 是 starmap 的异步(并行)版本。同样可以向任务函数传递多个参数;并且具有get()方法,获取结果组成的list。
def func(a, b): #starmap方法允许多个参数
return a
pool = multiprocessing.Pool()
result = pool.starmap_async(func, ((a0, b0), (a1, b1), ...)).get()
pool.close()
pool.join()
(4) 除了提到的这三种进程执行方式,常用还有 apply 、 apply_async 、 imap 等,常常需要根据数据量、计算资源、内存资源等来合理选择。
进程池常用的方法
(1) .close()
关闭进程池,关闭后不能往pool中增加新的子进程
(2) .join()
在关闭进程池后,可以调用join()函数等待已有子进程执行完毕。在调用这个方法后,程序将等待进程池中所有进程执行完毕,才会继续执行后续代码。
进程通信
多进程相比多线程最大的区别,就是进程是完全独立的,内存无法共享。如果要实现进程间数据共享,就需要采用特殊的方法,专门用于存储共享的数据。
暂时用不到>>>>>
参考资料