队列中的并行处理(使用Celery中的池)

时间:2011-10-07 22:30:09

标签: python parallel-processing threadpool multiprocessing django-celery

我正在使用Celery to queue jobs from a CGI application I made。我设置它的方式,Celery通过设置CELERYD_CONCURRENCY = 1= 2使每个作业一次运行一次或两次(因此它们不会挤占处理器或从内存中晃动消费)。由于我在StackOverflow上的建议,队列工作得很好。

这些工作中的每一项都需要相当长的时间(连续约30分钟),但具有令人尴尬的可并行性。出于这个原因,我使用Pool.map来拆分它并同时进行工作。它在命令行中运行良好,我使用新的多芯片芯片运行时间约为5分钟。

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

AssertionError:不允许守护进程生成子女

我注意到other peoplehad similar questions,但我找不到一个不需要完全放弃Pool.map并制作更复杂的线程代码的答案。

这里适当的设计选择是什么?我可以使用我的Celery队列轻松运行我的串行作业。我还可以在没有队列的情况下运行更快的并行化作业。我应该如何处理这个问题,是否有可能得到我想要的东西(两者队列和每个作业的并行化)?

我曾经有过一些想法(有些想法很讨厌):

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

提前多多感谢。

2 个答案:

答案 0 :(得分:0)

您需要的是管理

的工作流管理系统(WFMS)
  • 任务并发
  • 任务依赖
  • 任务嵌套

等等。

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

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

答案 1 :(得分:0)

我使用基于Twisted with forking和Gearman作业的多处理deamons正常查询。

试着看看Gearman。