如何避免腌制芹菜任务?

时间:2015-04-29 10:20:32

标签: python machine-learning celery pickle

我的场景如下:我有一个大型机器学习模型,由一群工人计算。实质上,工人计算自己的模型部分,然后与结果交换,以维持全局一致的模型状态。

因此,每个芹菜任务都会计算它自己的工作。 但这意味着,任务都没有无状态,这就是我的麻烦:如果我说some_task.delay( 123, 456 ),实际上我 NOT 在这里发送两个整数!

我发送完整的任务状态,在Celery的某处腌制。这种状态通常约为200 MB: - ((

我知道,在Celery中选择合适的序列化程序是可能的,但我的问题是如何挑选任何可能在任务中的数据。 如何挑选任务的参数? 这是来自celery / app / task.py的引用:

  def __reduce__(self):
    # - tasks are pickled into the name of the task only, and the reciever
    # - simply grabs it from the local registry.
    # - in later versions the module of the task is also included,
    # - and the receiving side tries to import that module so that
    # - it will work even if the task has not been registered.
    mod = type(self).__module__
    mod = mod if mod and mod in sys.modules else None
    return (_unpickle_task_v2, (self.name, mod), None)

我根本不希望这种情况发生。 有没有一个简单的方法,或者我只是被迫建立自己的芹菜(这是难以想象的)?

3 个答案:

答案 0 :(得分:1)

不要使用芹菜结果后端。使用单独的数据存储。

虽然您可以使用Task.ignore_result,但这意味着您无法跟踪任务状态等。

最佳解决方案是使用一个存储引擎(例如Redis)作为结果后端。 您应该设置一个单独的存储引擎(一个单独的Redis实例,或者像MongoDB一样,根据您的需要)来存储实际数据。

通过这种方式,您仍然可以看到任务的状态,但是大数据集不会影响芹菜的操作。

切换到JSON序列化程序可能会减少序列化开销,具体取决于您生成的数据的格式。但是,它无法解决在结果后端输入过多数据的根本问题。

结果后端可以处理相对少量的数据 - 一旦超过某个限制,就会开始阻止其主要任务的正常运行 - 任务状态的通信。

我建议更新您的任务,以便他们返回包含有用元数据的轻量级数据结构(以促进任务之间的协调),并将“真实”数据存储在专用存储解决方案中。

答案 1 :(得分:0)

您必须按照文档中的说明定义任务中的忽略结果:

  

任务。的 ignore_result

     

不存储任务状态。请注意,这意味着您无法使用AsyncResult检查任务是否已准备就绪,或获取其返回值。

答案 2 :(得分:-1)

那有点不受欢迎,但仍然。

我理解的是这里发生的事情。您有几个进程,它们与进程间通信并行执行大量计算。所以,不要不满意芹菜,你可以:

  • 使用zmq进行进程间通信(仅发送必要的数据),
  • 使用supervisor来管理和运行流程(numprocs尤其有助于运行多个相同的工作人员。)

虽然不需要编写自己的芹菜,但需要编写一些代码。