4

我正在使用Celery 对我制作的 CGI 应用程序中的作业进行排队。按照我的设置方式,Celery 通过设置CELERYD_CONCURRENCY = 1or使每个作业一次运行一个或两个= 2(因此它们不会拥挤处理器或因内存消耗而崩溃)。多亏了我在 StackOverflow 上得到的建议,队列工作得很好。

这些作业中的每一个都需要相当长的时间(大约 30 分钟串行),但具有令人尴尬的并行性。出于这个原因,我Pool.map习惯于拆分它并并行完成工作。它在命令行中运行良好,我使用新的多核芯片获得了大约 5 分钟的运行时间。

不幸的是,有一些限制不允许守护进程拥有子进程,当我在 CGI 队列中运行花哨的并行化代码时,我收到此错误:

AssertionError: 守护进程不允许有子进程

我注意到其他人有类似的问题,但我找不到不需要完全放弃Pool.map并制作更复杂的线程代码的答案。

这里合适的设计选择是什么?我可以使用我的 Celery 队列轻松运行我的串行作业。我还可以在没有队列的情况下运行我更快的并行化作业。我应该如何解决这个问题,是否可以获得我想要的(队列每个作业并行化)?

我有几个想法(有些很老套):

  • 发送到 Celery 队列的作业只是调用命令行程序。该程序可以随意使用 Pool,然后将结果数字和数据保存到文件中(就像现在一样)。
    缺点:我将无法检查作业的状态或查看它是否成功终止。此外,来自 CGI 的系统调用可能会导致安全问题。
  • 显然,如果队列中的作业非常多,我可以充分利用 CPU 资源(通过设置 CELERYD_CONCURRENCY = 6 左右);这将允许许多人同时“排在队列的最前面”。
    缺点:每个工作都会在队列最前面花费大量时间;如果队列未满,则不会有加速。此外,许多部分完成的作业将同时存储在内存中,使用更多的 RAM。
  • 使用 Celery 的 @task 在子作业中并行化。然后,我不会设置 CELERYD_CONCURRENCY = 1,而是将其设置为 6(或者我希望一次允许在内存中的许多子作业)。
    缺点:首先,我不确定这是否会成功避免“任务中的任务”问题。但是,队列位置的概念可能会丢失,许多部分完成的作业可能会立即进入内存。
  • 也许有一种方法可以调用 Pool.map 并指定线程是非守护线程的?或者也许我可以使用更轻量级的东西来代替 Pool.map?这类似于对另一个开放的 StackOverflow 问题采取的方法。另外,我应该注意,我通过 Pool.map 利用的并行化类似于线性代数,并且没有进程间通信(每个都独立运行并返回其结果而不与其他人交谈)。
  • 扔掉 Celery 并使用 multiprocessing.Queue。那么也许有一些方法可以为我使用的每个线程使用相同的“线程深度”(,也许所有线程都可以使用同一个池,避免嵌套)?

提前非常感谢。

4

2 回答 2

0

您需要的是一个工作流管理系统 (WFMS),用于管理

  • 任务并发
  • 任务依赖
  • 任务嵌套

除其他事项外。

从非常高级的角度来看,WFMS 位于像 celery 这样的任务池之上,并将准备好执行的任务提交到池中。它还负责打开一个巢并相应地提交巢中的任务。

我已经开发了一个系统来做到这一点。它被称为pomsets。试试看,如有任何问题,请随时向我发送。

于 2011-10-12T00:25:15.007 回答
0

我使用基于 Twisted 的多进程守护程序,并正常进行分叉和 Gearman 作业查询。

试着看看 Gearman。

于 2011-10-16T12:16:13.987 回答