【问题标题】:Python multiprocessing - reassigning jobs dynamically from pool - without async?Python 多处理 - 从池中动态重新分配作业 - 没有异步?
【发布时间】:2018-07-18 13:57:56
【问题描述】:

所以我有一批 1000 个任务,我使用 parmap/python 多处理模块分配给 8 个内核(双至强机器 16 个物理内核)。目前这使用同步运行。

问题在于,通常其中 1 个核心远远落后于其他核心,并且在所有其他核心完成工作后仍有几项工作/任务要完成。这可能与核心速度(较旧的计算机)有关,但更有可能是由于某些任务比其他任务更困难 - 因此获得稍微困难​​的工作的 1 个核心变得滞后......

我在这里有点困惑——但这就是异步并行化的作用吗?我之前尝试过使用它,但是因为这一步是一个非常大的处理步骤的一部分——不清楚如何创建一个屏障来强制程序等待所有异步进程完成。

感谢任何类似问题/答案的建议/链接。

[编辑]澄清一下,这些进程可以独立运行,它们都将数据保存到磁盘并且不共享变量。

【问题讨论】:

    标签: python synchronization multiprocessing pool


    【解决方案1】:

    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 开销。

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

    【讨论】:

      【解决方案2】:

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

      http://www.celeryproject.org/

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

      【讨论】:

      • 感谢您的建议,这是正确的调查方向。似乎这些工具对于我不涉及 Web 部署或云的应用程序来说太过分了。也许较小的任务排队工具之一可能更易于使用?!
      • 您可以构建简单的。这些类型的项目的好处是,如果您将代码编写为工具,一旦完成,您将开始在大量不同的项目中找到用法。你会发现在一个项目中看似矫枉过正的东西在另一个项目中却是救命稻草。
      • 好的,看来这不是正确的解决方案;从技术上讲,多处理模块应该可以满足我的需求。
      • 异步允许等待 IO 继续进行的应用程序,CPU 绑定计算仍然是同步的,但是当您主要等待来自 IO 的数据时,异步成为一个巨大的速度提升,因为它可以同时打开 100 个连接,并允许您在数据进入时对其进行处理。
      猜你喜欢
      • 1970-01-01
      • 2020-10-30
      • 2021-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-05
      • 2019-02-14
      • 1970-01-01
      相关资源
      最近更新 更多