Python:使用chunk时在多处理中实现负载平衡的最佳方法是什么

时间:2018-01-15 15:21:24

标签: python multiprocessing

例如,将6个任务中的17个任务分配给2个进程将是2 * 6 + 5,也就是说,每个进程得到6个,但剩下5个任务。我认为最好的方法是让剩余的任务在2个进程中均匀分布。所以我做了一个测试,看看mp.Pool是否正在这样做。这是一个测试脚本

import multiprocessing as mp
import time
def f(x):
    time.sleep(0.1)
    print(mp.current_process())

if __name__ == "__main__":
    p = mp.Pool(2)
    p.map(f, range(17),6)

将输出

<ForkProcess(ForkPoolWorker-1, started daemon)>
<ForkProcess(ForkPoolWorker-2, started daemon)>
<ForkProcess(ForkPoolWorker-1, started daemon)>
<ForkProcess(ForkPoolWorker-2, started daemon)>
<ForkProcess(ForkPoolWorker-1, started daemon)>
<ForkProcess(ForkPoolWorker-2, started daemon)>
<ForkProcess(ForkPoolWorker-1, started daemon)>
<ForkProcess(ForkPoolWorker-2, started daemon)>
<ForkProcess(ForkPoolWorker-1, started daemon)>
<ForkProcess(ForkPoolWorker-2, started daemon)>
<ForkProcess(ForkPoolWorker-1, started daemon)>
<ForkProcess(ForkPoolWorker-2, started daemon)>
<ForkProcess(ForkPoolWorker-1, started daemon)>
<ForkProcess(ForkPoolWorker-1, started daemon)>
<ForkProcess(ForkPoolWorker-1, started daemon)>
<ForkProcess(ForkPoolWorker-1, started daemon)>
<ForkProcess(ForkPoolWorker-1, started daemon)>

注意最后5行,显然剩下的任务全部分配到一个进程,然后所有其他进程都无关。

是否有一种在Pool.map中自动分发剩余块的好方法?

1 个答案:

答案 0 :(得分:2)

不是简单的参数变化。并且当您将流程分配给工作人员时,您不会重新分配流程。

当然你可以写一个解决方法:

if __name__ == "__main__":
    p = mp.Pool(2)
    tasks = 17
    chunksize = 6

    p.map(f, range((tasks / chunksize) * chunksize), 6)
    p.map(f, range((tasks / chunksize) * chunksize + 1, tasks))

这首先是完整的块。然后将剩余的五个任务逐个分配给池而不是块。这将产生预期的结果。

但是,我不确定为什么这很重要。如果任务需要很长时间才能完成,那么使用块有什么意义呢?随着时间花在工人身上,不会有任何表现提升。默认的块大小为1时,您可以完全正常工作,只要一个任务空闲,就可以将任务分配给工作人员。

如果任务在极短的时间内完成,并且将更多时间用于逐个向工作人员传输数据,那么Chunksize可以提升性能。如果是这种情况,那么如果最后一个任务是由一个工人完成的,那么完成这几个任务的时间将是无关紧要的并不重要。

这个特殊的例子当然是最糟糕的情况。在更现实的情况下,通常情况下不会有任何性能损失。想象一下,成批的数万个任务以35个块的形式发送给工人。不可避免的是,在批处理过程中,工人们分道扬and,他们没有完全同时完成。一些块会更快,一些更慢。现在让我们假设您的余数不是34而是17.如果工作者A现在已经启动了最后一个完整的块并且当工作者B完成其最后一个完整的块并且得到17的剩余部分时处理了不到一半的任务,那么它将是可能工人B实际上在工人A之前完成,尽管已处理剩余集。

但是如果有理由先做块,剩下的就分发给工人,那么这就是做这件事的方法。我确实认为您正在尝试解决一个不是问题的问题,而且为了难以衡量的性能提升,您只会为代码添加更多复杂性。