簡體   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