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

相关问题