关于python的进程池对象的一些方法的说明
作者:互联网
python提供的multiprocessing
模块可以方便的利用多进程对任务进行加速。其中,multiprocessing.Pool
可以生成一个包含指定数量进程的进程池,来执行任务。要向Pool
对象中提交任务,有许多方法可供选择;也正是因为如此,它们的区别以及适用场景可能会让人觉得困惑。
我在Stack Overflow上发现了一个有助于帮助理解这一点的回答,因此翻译过来。
关于imap(imap_unordered)
和map(map_async)
,主要有两点不同:
- 处理用户传入的可迭代对象的方式
- 返回计算结果的方式
1、处理用户传入的可迭代对象的方式
map
方法首先将传入的可迭代对象转化为列表(假设它们之前并非列表),然后将列表分块,最后将这些数据块传入进程池中的各个进程。将可迭代对象转化为列表并分块要比逐个将可迭代对象中的元素传入各个进程更高效——特别是当可迭代对象很大时。然而,由于必须将整个列表都存入内存才能进行分块操作,因此这种方法具有很高的内存消耗。
imap
方法并不会将可迭代对象转化为列表,也不会进行分块(默认情况下)。它会逐个遍历可迭代对象,每次获取一个值,然后将其传递给工作进程。因此,不必有内存溢出的担忧,但同时,对于较大的可迭代对象,其工作效率会降低(逐个取值放入进程,意味着操作系统需要不断的切换进程——这需要开销)。不过,你可以通过设置chunksize
参数为较大的整数(其默认值为1
)来缓解这个问题。
2、返回计算结果的方式
对于imap(imap_unordered)
,你可以在各个工作进程完成各自的计算时就拿到其计算结果,而不必等到所有的进程都完成。
使用map_async
时,会立即返回一个AsyncResult
对象,但一直要等到所有的工作进程完成它们的计算时,你才能从AsyncResult
对象中拿到计算结果(从AsyncResult
对象中拿到的结果与使用map
方法得到的结果相同,是一个列表;map
方法实际上就是调用了map_async(...).get()
)。所以,你绝无可能得到部分结果——要么得到全部结果,要么什么也得不到。
imap
和imap_unordered
都会立即返回一个可迭代对象,其区别是:使用imap
时,一旦进程计算完成,结果就会从可迭代对象中产生,同时仍然保持输入的可迭代对象的顺序;使用imap_unordered
时,结果输出方式与imap
相同,只是结果的顺序与输入无法保持一致。
下面用具体的例子来说明一下。
import multiprocessing
import time
def func(x):
time.sleep(x)
return x + 2
if __name__ == "__main__":
p = multiprocessing.Pool()
start = time.time()
for x in p.imap(func, [1,5,3]):
print("{} (Time elapsed: {}s)".format(x, int(time.time() - start)))
输出如下:
3 (Time elapsed: 1s)
7 (Time elapsed: 5s)
5 (Time elapsed: 5s)
解释一下为何出现这样的情况:
首先,由于选择了默认参数,进程池对象p
中的进程数量为CPU的核数,这里是8。然后通过imap
方法,向各个工作进程分派了任务,由于参数列表中只有3个元素,因此,一共只需要调用三个工作进程即可,且三个进程是同时处理任务的。
进程1,睡眠1秒,返回3;进程2,睡眠5秒,返回7;进程3,睡眠3秒,返回5。但因为imap
方法的返回值与传入的参数同序,因此,控制台先打印进程1的结果,在打印进程2的结果是,会发现进程3的结果马上就打印出来,这是因为进程3的任务早已先于进程2完成,只不过由于需要按照顺序返回,所以必须在进程2的结果被获取之后才打印。
类似的,如果采用imap_unordered
,那么,打印的结果如下:
3 (Time elapsed: 1s)
5 (Time elapsed: 3s)
7 (Time elapsed: 5s)
由于没有了顺序的限制,因此,哪个进程先执行完,哪个的结果先输出。
如果采用map
或map_async().get()
,那么结果如下:
3 (Time elapsed: 5s)
7 (Time elapsed: 5s)
5 (Time elapsed: 5s)
由于必须是同时输出结果,因此,所有的时间间隔都是5s。
因此,当以下条件满足时,优先选用imap/imap_unordered
而不是map/map_async
:
- 作为参数的可迭代对象过大,以至于将其转为列表并分块有内存溢出的风险;
- 你希望结果的输出是有序的。
标签:map,迭代,python,elapsed,对象,Time,进程,imap 来源: https://www.cnblogs.com/sunjiawei-2018/p/14752520.html