Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 多处理。池:什么';映射异步和imap之间的区别是什么?_Python_Multiprocessing_Python Multiprocessing - Fatal编程技术网

Python 多处理。池:什么';映射异步和imap之间的区别是什么?

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

我试图学习如何使用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 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无序
    over
    map\u异步
    的主要原因是:

  • 您的iterable足够大,因此将其转换为列表会导致内存不足/使用过多
  • 您希望能够在所有结果完成之前开始处理这些结果

  • 公认的答案是,对于未排序的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的结果之前完成,但结果似乎被写入了