Python多处理-从池动态重新分配作业-无需异步?

时间:2018-07-18 13:57:56

标签: python synchronization multiprocessing pool

因此,我使用parmap / python多处理模块将一千个任务分配给8个内核(双至强计算机16个物理内核)。当前,这使用同步运行。

问题在于,通常情况下,其中一个内核远远落后于其他内核,而在所有其他内核完成工作后,仍有几个作业/任务需要完成。这可能与核心速度(旧计算机)有关,但更有可能是由于某些任务比其他任务更困难-因此,工作难度稍高的1核心会变得迟钝...

我在这里有点困惑-但这是异步并行化的作用吗?我曾经尝试过使用它,但是因为此步骤是非常大的处理步骤的一部分-尚不清楚如何创建障碍来迫使程序等待所有异步进程完成。

任何与类似问题/答案有关的建议/链接都会受到赞赏。

[EDIT]为了明确起见,这些进程可以独立运行,它们都将数据保存到磁盘,并且不共享变量。

2 个答案:

答案 0 :(得分:1)

您确实需要研究创建微服务和使用队列池。例如,您可以将一份作业列表放入celery或redis中,然后让微服务一次从队列中拉出并处理作业。完成后,他们拉下一个项目,依此类推。这样,您的负载将根据准备情况进行分配,而不是基于预设列表。

http://www.celeryproject.org/

https://www.fullstackpython.com/task-queues.html

答案 1 :(得分:0)

parmap作者在此处

默认情况下,无论是在多处理还是在parmap中,任务都被分为多个块,并且将块发送到每个多处理进程(请参见multiprocessing documentation)。其背后的原因是,在许多情况下,将任务分别发送到流程会引入大量的计算开销。如果同时分块发送多个任务,则可以减少开销。

在多处理过程中,每个块的任务数由chunksize(在parmap中由pm_chunksize)控制。默认情况下,chunksize计算为"number of tasks"/(4*"pool size"),四舍五入(请参见multiprocessing source code)。因此,对于您的情况,每块1000 /(4 * 4)= 62.5-> 63个任务。

如果像您一样,许多计算量大的任务属于同一块,那么该块将需要很长时间才能完成。

解决此问题的一种“便宜又轻松”的方法是传递一个较小的chunksize值。请注意,使用极端的chunksize=1可能会带来不希望的较大的CPU开销。

从长远来看,其他答案中建议的适当的排队系统是一个更好的解决方案,但对于一次性问题来说可能是一个过大的杀伤力。