Python 多处理。池:什么';映射异步和imap之间的区别是什么?
我试图学习如何使用Python的Python 多处理。池:什么';映射异步和imap之间的区别是什么?,python,multiprocessing,python-multiprocessing,Python,Multiprocessing,Python Multiprocessing,我试图学习如何使用Python的多处理包,但我不理解map\u async和imap之间的区别。 我注意到map\u async和imap都是异步执行的。那我什么时候应该用一个来代替另一个呢?我应该如何检索map\u async返回的结果 我应该用这样的东西吗 def test(): result = pool.map_async() pool.close() pool.join() return result.get() result=test() for i
多处理
包,但我不理解map\u async
和imap
之间的区别。
我注意到map\u async
和imap
都是异步执行的。那我什么时候应该用一个来代替另一个呢?我应该如何检索map\u async
返回的结果
我应该用这样的东西吗
def test():
result = pool.map_async()
pool.close()
pool.join()
return result.get()
result=test()
for i in result:
print i
imap
/imap\u unordered
和map
/map\u async
之间有两个关键区别:
map
通过将iterable转换为列表(假设它还不是列表)、将其分解为块并将这些块发送到池中的工作进程来使用iterable。将iterable分解成块比每次在进程之间传递一个iterable中的每一项性能更好,特别是当iterable很大时。然而,将iterable转换为一个列表以便将其分块可能会有非常高的内存开销,因为整个列表都需要保存在内存中
imap
不会将您提供的iterable转换为列表,也不会将其分解为块(默认情况下)。它将一次迭代一个iterable元素,并将每个元素发送给一个工作进程。这意味着您不会因为将整个iterable转换为一个列表而损失内存,但也意味着对于大型iterable,由于缺少分块,性能会变慢。但是,可以通过传递一个大于默认值1的chunksize
参数来缓解这种情况
imap
/imap\u无序
和map
/map\u异步
之间的另一个主要区别是,使用imap
/imap\u无序
,您可以在工作人员准备好后立即开始接收他们的结果,而不必等待所有工作人员完成。使用map\u async
,会立即返回AsyncResult
,但在所有结果都被处理之前,您无法从该对象实际检索结果,此时它返回与map
相同的列表(map
实际上在内部实现为map\u async(…).get()
)。没有办法得到部分结果;你要么拥有全部结果,要么什么都没有
imap
和imap\u unordered
都立即返回iterables。使用imap
,结果将在准备就绪后立即从iterable中产生,同时仍保留输入iterable的顺序。当imap_无序时
,无论输入iterable的顺序如何,结果都将在准备就绪后立即生成。那么,假设你有:
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.imap\u unordered
而不是p.imap
,您将看到:
3 (Time elapsed: 1s)
5 (Time elapsed: 3s)
7 (Time elapsed: 5s)
3 (Time elapsed: 5s)
7 (Time elapsed: 5s)
5 (Time elapsed: 5s)
如果使用p.map
或p.map\u async().get()
,您将看到:
3 (Time elapsed: 1s)
5 (Time elapsed: 3s)
7 (Time elapsed: 5s)
3 (Time elapsed: 5s)
7 (Time elapsed: 5s)
5 (Time elapsed: 5s)
因此,使用imap
/imap\u无序
overmap\u异步
的主要原因是:
公认的答案是,对于未排序的imap_“结果一准备好就会产生”,其中可能会推断结果将按完成顺序返回。但我只想说清楚,这在总体上是不正确的。文档说明结果以任意顺序返回。考虑下面的程序,该程序使用池大小为4、迭代大小为20和块大小为5的值。worker函数根据其传递的参数休眠不同的时间,这也确保池中没有一个进程捕获所有提交的任务。因此,我希望池中的每个进程都有
20/4=5
任务要处理:
来自多处理导入池的
导入时间
def工人(x):
打印(f'x={x}',flush=True)
睡眠时间(.1*(20-x))
#返回传递参数的大致完成时间:
return time.time(),x
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
池=池(4)
结果=池。imap_无序(工作者,范围(20),chunksize=5)
对于t,结果中的x:
打印('结果:',t,x)
印刷品:
x = 0
x = 5
x = 10
x = 15
x = 16
x = 17
x = 11
x = 18
x = 19
x = 6
result: 1621512513.7737606 15
result: 1621512514.1747007 16
result: 1621512514.4758775 17
result: 1621512514.675989 18
result: 1621512514.7766125 19
x = 12
x = 1
x = 13
x = 7
x = 14
x = 2
result: 1621512514.2716103 10
result: 1621512515.1721854 11
result: 1621512515.9727488 12
result: 1621512516.6744206 13
result: 1621512517.276999 14
x = 8
x = 9
x = 3
result: 1621512514.7695887 5
result: 1621512516.170747 6
result: 1621512517.4713914 7
result: 1621512518.6734042 8
result: 1621512519.7743165 9
x = 4
result: 1621512515.268784 0
result: 1621512517.1698637 1
result: 1621512518.9698756 2
result: 1621512520.671273 3
result: 1621512522.2716706 4
您可以清楚地看到,这些结果并不是按完成顺序产生的。例如,我已被返回1621512519.7743165 9
,然后是1621512515.268784 0
,工作函数返回的结果比之前返回的结果早4秒多。但是,如果我将chunksize值更改为1,则打印输出为:
x = 0
x = 1
x = 2
x = 3
x = 4
result: 1621513028.888357 3
x = 5
result: 1621513028.9863524 2
x = 6
result: 1621513029.0838938 1
x = 7
result: 1621513029.1825204 0
x = 8
result: 1621513030.4842813 7
x = 9
result: 1621513030.4852195 6
x = 10
result: 1621513030.4872172 5
x = 11
result: 1621513030.4892178 4
x = 12
result: 1621513031.3908074 11
x = 13
result: 1621513031.4895358 10
x = 14
result: 1621513031.587289 9
x = 15
result: 1621513031.686152 8
x = 16
result: 1621513032.1877549 15
x = 17
result: 1621513032.1896958 14
x = 18
result: 1621513032.1923752 13
x = 19
result: 1621513032.1923752 12
result: 1621513032.2935638 19
result: 1621513032.3927407 18
result: 1621513032.4912949 17
result: 1621513032.5884912 16
这是完成顺序。但是,我不愿意声明,如果指定chunksize值为1,则imap_unordered
将始终返回可用的结果,尽管基于此实验的情况似乎是这样,因为文档中没有这样的声明
讨论
当指定chunksize为5时,将20个任务放置在单个输入队列中,以便池中的4个进程以大小为5的块进行处理。因此,一个空闲的进程将从队列中取出下一块5个任务,并在再次空闲之前依次处理其中的每一个任务。因此,第一个进程将处理x
参数0到4,第二个进程处理x
参数5到9,等等。这就是为什么您会看到初始x
值打印为0、5、10和15
但是,虽然x
参数0的结果在x
参数9的结果之前完成,但结果似乎被写入了