Python 3:Pool是否保持传递给地图的原始数据顺序?

时间:2016-12-22 00:13:26

标签: python multithreading python-3.x multiprocessing threadpool

我编写了一个小脚本来分配4个线程之间的工作负载,并测试结果是否保持有序(关于输入的顺序):

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中存储每个map函数的结果时,q是否真的保留了原始输入的顺序?< / p>

旁注:我问这个,因为我需要一种简单的方法来并行化几个工作人员的工作。在某些情况下,排序是无关紧要的。但是,在某些情况下,结果(如q)必须按原始顺序返回,因为我使用了依赖于有序数据的附加reduce函数。

性能:在我的机器上,此操作比单个进程上的正常执行速度快4倍(正如预期的那样,因为我有4个核心)。此外,所有4个核心在运行时都处于100%使用状态。

2 个答案:

答案 0 :(得分:23)

Pool.map结果已订购。如果你需要订单,很棒;如果不这样做,Pool.imap_unordered可能是一个有用的优化。

请注意,虽然您从Pool.map收到结果的顺序是固定的,但计算它们的顺序是任意的。

答案 1 :(得分:8)

文档将其记为"parallel equivalent of the map() built-in function"。由于保证map保留订单,multiprocessing.Pool.map也会保证订单。