多处理:执行顺序

时间:2017-04-10 18:11:38

标签: python multiprocessing

我正在尝试以下代码:

from multiprocessing import Pool

def f(x):    
    return x

if __name__ == '__main__':
    p = Pool(5)
    print(p.map(f, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13]))

据我所知,5个处理器获得0, 1, 2, 3, 4来执行操作。如果处理器1完成了它的工作,它会立即得到5,而其余的处理器忙于1,2,3,4或者所有处理器的代码都完成,以便下一批将一起得到{{ 1}}等等。如果后来发生了如何实现上面的代码,那么当处理器进入空闲状态时,它会分配给它的新工作?

如何测试实施?

2 个答案:

答案 0 :(得分:2)

Threadpool会立即生成一个新线程(添加到您的示例中)。注意线程4如何花费足够长的时间才能启动第12个任务。

PS我刚注意到你忘记了10。

from multiprocessing import Pool
import time
import random

def f(x):
    print "Enter %s" % x
    time.sleep( random.randrange(1,100,1)/10.0 )
    print "Exit %s" % x
    return x

if __name__ == '__main__':
    p = Pool(5)
    print(p.map(f, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13]))

Enter 0
Enter 1
Enter 2
Enter 3
Enter 4
Exit 0
Enter 5
Exit 3
Enter 6
Exit 2
Enter 7
Exit 5
Enter 8
Exit 1
Enter 9
Exit 6
Enter 11
Exit 11
Enter 12
Exit 4
Enter 13
Exit 7
Exit 12
Exit 9
Exit 8
Exit 13
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13]

答案 1 :(得分:1)

是的,这种情况是可能的。首先将输入分区为单独的任务。当任务的大小不均匀(就处理时间而言)时,问题就出现了,并且它们太少而无法填补空白。

来自documentation

  

地图 func 可迭代 [, chunksize ])

     

此方法将iterable切割为多个块,并将其作为单独的任务提交给进程池。 (近似)大小   可以通过将chunksize设置为正数来指定这些块   整数。

实施例

为了说明这种行为,我更改了f(x),因此需要x秒才能完成。

from multiprocessing import Pool
import time
import threading

def f(x):
    print('x: ' + str(x) + '\tThread ID: ' + str(threading.get_ident()))
    time.sleep(x)

if __name__ == '__main__':
    chunksize = 3
    with Pool(2) as p:
        p.map(f, [10, 1, 1, 1, 1, 1], chunksize)

输入数组[10, 1, 1, 1, 1, 1]被划分为len(arr) / chunksize = 2个组:

[10, 1, 1]  # For thread 1, takes 12 seconds to finish
[ 1, 1, 1]  # For thread 2, takes 3 seconds to finish

因此,线程2将在3秒后完成,而线程1将继续工作9秒钟。

示例输出:

x: 10   Thread ID: 8556
x: 1    Thread ID: 59180
x: 1    Thread ID: 59180
x: 1    Thread ID: 59180
x: 1    Thread ID: 8556
x: 1    Thread ID: 8556

如果您发现自己处于这种情况,那么您可以强制使用较小的chunksize。值1确保尽可能平衡工作负载,但代价是更高的开销。