4

我已經寫了一個小腳本,以4個線程之間分配工作量,測試結果是否保持有序的(在相對於輸入的順序):Python 3:池是否保持傳遞給映射的數據的原始順序?

from multiprocessing import Pool 
import numpy as np 
import time 
import random 


rows = 16 
columns = 1000000 

vals = np.arange(rows * columns, dtype=np.int32).reshape(rows, columns) 

def worker(arr): 
    time.sleep(random.random())  # let the process sleep a random 
    for idx in np.ndindex(arr.shape): # amount of time to ensure that 
     arr[idx] += 1     # the processes finish at different 
             # time steps 
    return arr 

# create the threadpool 
with Pool(4) as p: 
    # schedule one map/worker for each row in the original data 
    q = p.map(worker, [row for row in vals]) 

for idx, row in enumerate(q): 
    print("[{:0>2}]: {: >8} - {: >8}".format(idx, row[0], row[-1])) 

對我來說,這始終會導致:

[00]:  1 - 1000000 
[01]: 1000001 - 2000000 
[02]: 2000001 - 3000000 
[03]: 3000001 - 4000000 
[04]: 4000001 - 5000000 
[05]: 5000001 - 6000000 
[06]: 6000001 - 7000000 
[07]: 7000001 - 8000000 
[08]: 8000001 - 9000000 
[09]: 9000001 - 10000000 
[10]: 10000001 - 11000000 
[11]: 11000001 - 12000000 
[12]: 12000001 - 13000000 
[13]: 13000001 - 14000000 
[14]: 14000001 - 15000000 
[15]: 15000001 - 16000000 

問題:那麼,是否真的Pool保持原始輸入的順序存儲在各q功能map的結果是什麼時候?

旁註:我在問這個問題,因爲我需要一個簡單的方法來並行化幾個工作人員的工作。在某些情況下,排序是無關緊要的。但是,在某些情況下,結果(如q)必須按原始順序返回,因爲我正在使用依賴於有序數據的額外減少功能。

性能:在我的機器上,這個操作比單個進程的正常執行速度快4倍(因爲我有4個內核)。此外,在運行期間,所有4個內核的使用率都達到100%。

回答

6

Pool.map結果已訂購。如果你需要點餐,太棒了;如果你沒有,Pool.imap_unordered可能是一個有用的優化。

請注意,雖然您從Pool.map收到結果的順序是固定的,但它們的計算順序是任意的。

+1

爲什麼'imap_unordered''優化'?速度更快嗎? – daniel451

+3

@ascenator:如果稍後的輸出先準備就緒,則可以使用它們而不必等待較早的輸出完成。 – user2357112

3

該文件記錄爲"parallel equivalent of the map() built-in function"。由於map保證了訂單,multiprocessing.Pool.map也作出了保證。

+0

是否保持訂單成本合理的計算時間? – daniel451

+1

我會懷疑它。 「imap_unordered」的優點(由@ user2357112報告)是,您可以立即開始處理結果,因爲它們在主進程中可用。通過'Pool.map',您需要等到所有n-1個項目都有結果,然後才能開始處理第n個項目。 – mgilson

相關問題