繁体   English   中英

使用 tqdm 作为进度条时来自多处理的 join() 输出

[英]join() output from multiprocessing when using tqdm for progress bar

我正在使用与此示例类似的构造来并行运行我的处理以及由tqdm提供的进度条...

from multiprocessing import Pool
import time
from tqdm import *

def _foo(my_number):
   square = my_number * my_number
   return square 

if __name__ == '__main__':
    with Pool(processes=2) as p:
        max_ = 30
        with tqdm(total=max_) as pbar:
            for _ in p.imap_unordered(_foo, range(0, max_)):
                pbar.update()
    results = p.join()  ## My attempt to combine results

虽然results始终是NoneType ,但我无法弄清楚如何组合我的结果。 我知道with ...:将在完成时自动关闭它正在使用的内容。

我试过用以下方法去掉外部with:

if __name__ == '__main__':
    max_ = 10
    p = Pool(processes=8)
    with tqdm(total=max_) as pbar:
        for _ in p.imap_unordered(_foo, range(0, max_)):
            pbar.update()
    p.close()
    results = p.join()
    print(f"Results : {results}")

对如何join()我的结果感到困惑?

您对p.join()的调用只是等待所有池进程结束并返回None 此调用实际上是不必要的,因为您将池用作上下文管理器,即您已将with Pool(processes=2) as p: )。 当该块终止时, p.terminate()进行隐式调用,该调用会立即终止池进程和任何可能正在运行或排队运行的任务(在您的情况下没有)。

实际上,它是对p.imap_unordered调用返回的迭代器进行迭代,该迭代器从您的工作函数_foo返回每个返回值。 但是由于您使用的是imap_unordered方法,因此返回的结果可能不是按提交顺序排列的。 换句话说,您不能假设返回值将连续为 0、1、...、4、9 等。有很多方法可以处理这个问题,例如让您的工作函数返回原始参数以及平方值:

from multiprocessing import Pool
import time
from tqdm import *

def _foo(my_number):
   square = my_number * my_number
   return my_number, square # return the argunent along with the result

if __name__ == '__main__':
    with Pool(processes=2) as p:
        max_ = 30
        results = [None] * 30; # preallocate the resulys array
        with tqdm(total=max_) as pbar:
            for x, result in p.imap_unordered(_foo, range(0, max_)):
                results[x] = result
                pbar.update()
        print(results)

第二种方法是不使用imap_unordered ,而是使用带有回调函数的apply_async 这样做的缺点是,对于大型可迭代对象,您无法像使用imap_unordered那样指定chunksize参数:

from multiprocessing import Pool
import time
from tqdm import *

def _foo(my_number):
   square = my_number * my_number
   return square

if __name__ == '__main__':
    def my_callback(_): # ignore result
        pbar.update() # update progress bar when a result is produced

    with Pool(processes=2) as p:
        max_ = 30
        with tqdm(total=max_) as pbar:
            async_results = [p.apply_async(_foo, (x,), callback=my_callback) for x in range(0, max_)]
            # wait for all tasks to complete:
            p.close()
            p.join()
            results = [async_result.get() for async_result in async_results]
        print(results)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM