首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >multiprocessing.Pool: map_async和imap有什么区别?

multiprocessing.Pool: map_async和imap有什么区别?
EN

Stack Overflow用户
提问于 2014-10-23 11:23:30
回答 2查看 107K关注 0票数 225

我正在尝试学习如何使用Python的multiprocessing包,但我不明白map_asyncimap之间的区别。我注意到map_asyncimap都是异步执行的。那么我应该在什么时候使用一个而不是另一个呢?我应该如何检索map_async返回的结果

我应该使用这样的东西吗?

代码语言:javascript
复制
def test():
    result = pool.map_async()
    pool.close()
    pool.join()
    return result.get()

result=test()
for i in result:
    print i
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-10-23 12:51:42

imap/imap_unorderedmap/map_async之间有两个主要区别

  1. 使用您传递给他们的迭代器的方式。
  2. 返回结果给您的方式。

map通过将迭代器转换为列表(假设它还不是一个列表),将其分解成块,并将这些块发送到Pool中的工作进程来消耗迭代器。将迭代器分成块比在进程之间一次传递一个迭代器中的每个项要好-特别是当可迭代器很大的时候。然而,将可迭代变量转换为列表以将其分块可能会有非常高的内存成本,因为整个列表将需要保存在内存中。

imap不会将您给出的迭代值转换为列表,也不会将其分解成块(默认情况下)。它将一次迭代一个可迭代元素,并将每个元素发送到一个工作进程。这意味着你不需要将整个迭代器转换成一个列表,但这也意味着对于大的迭代器,由于缺少分块,性能会变慢。但是,可以通过传递大于默认值1的chunksize参数来缓解此问题。

imap/imap_unorderedmap/map_async之间的另一个主要区别是,使用imap/imap_unordered,您可以在工作人员准备好后立即开始接收结果,而不必等待所有工作人员完成。使用map_async时,会立即返回一个AsyncResult,但在处理完所有结果之前,您实际上无法从该对象检索结果,此时它会返回与map相同的列表(map实际上在内部实现为map_async(...).get())。没有办法获得部分结果;您要么得到整个结果,要么什么都没有。

imapimap_unordered都会立即返回可迭代对象。使用imap,一旦迭代器准备好,结果就会从迭代器中产生,同时仍然保留输入迭代器的顺序。使用imap_unordered,无论输入迭代的顺序如何,只要结果准备就绪,就会得到结果。所以,假设你有这个:

代码语言:javascript
复制
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)))

这将输出:

代码语言:javascript
复制
3 (Time elapsed: 1s)
7 (Time elapsed: 5s)
5 (Time elapsed: 5s)

如果您使用p.imap_unordered而不是p.imap,您将看到:

代码语言:javascript
复制
3 (Time elapsed: 1s)
5 (Time elapsed: 3s)
7 (Time elapsed: 5s)

如果您使用p.mapp.map_async().get(),您将看到:

代码语言:javascript
复制
3 (Time elapsed: 5s)
7 (Time elapsed: 5s)
5 (Time elapsed: 5s)

因此,在map_async上使用imap/imap_unordered的主要原因是:

  1. 迭代程序足够大,将其转换为列表会导致内存耗尽/使用过多内存。
  2. 您希望能够在所有结果完成之前开始处理结果。
票数 605
EN

Stack Overflow用户

发布于 2021-05-20 20:26:33

公认的答案是,对于imap_unordered来说,“结果一准备好就会产生”,其中可能会推断出结果将按完成的顺序返回。但我只想说清楚,这通常不是真的。文档说明结果是以任意顺序返回的。考虑下面的程序,它使用池大小为4,可迭代大小为20,块大小为5的值。worker函数根据其传递的参数休眠一段可变的时间,这也确保池中没有一个进程占用所有提交的任务。因此,我希望池中的每个进程都有要处理的20 / 4 = 5任务:

代码语言:javascript
复制
from multiprocessing import Pool
import time

def worker(x):
    print(f'x = {x}', flush=True)
    time.sleep(.1 * (20 - x))
    # return approximate completion time with passed argument:
    return time.time(), x

if __name__ == '__main__':
    pool = Pool(4)
    results = pool.imap_unordered(worker, range(20), chunksize=5)
    for t, x in results:
        print('result:', t, x)

打印:

代码语言:javascript
复制
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

您可以清楚地看到,这些结果并不是按完成顺序产生的。例如,worker函数返回的1621512519.7743165 9后跟1621512515.268784 0,比之前返回的结果早了4秒。但是,如果我将chunksize值更改为1,则打印输出如下所示:

代码语言:javascript
复制
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

这是按完成顺序排列的。但是,如果指定块大小值1,那么imap_unordered将始终返回可用的结果,这一点我不敢断言,尽管根据这个实验似乎是这样的,因为文档中没有这样的声明。

讨论

当指定块大小为5时,这20个任务被放在一个输入队列中,供池中的4个进程以大小为5的块进行处理。因此,空闲的进程将从队列中取出下一个包含5个任务的块,并在再次空闲之前依次处理每个任务。因此,第一个进程将处理x参数0到4,第二个进程处理x参数5到9,等等。这就是为什么您会看到初始x值打印为0、5、10和15。

但是,虽然x参数0的结果在x参数9的结果之前完成,但似乎结果作为块一起写出,因此x参数0的结果将不会返回,直到在同一块中排队的x参数的结果(即1、2、3和4)也可用。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26520781

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档