我正在开展一个项目来并行化一些繁重的模拟工作。每次运行大约需要两分钟,占用100%的可用CPU功率,并生成超过100 MB的数据。为了执行模拟的下一步,需要将这些结果合并为一个巨大的结果。
请注意,这将在高性能系统上运行(目前在具有16 GB RAM和12个内核的计算机上进行测试,但可能会升级到更大的硬件)
我可以使用芹菜作业组轻松调度其中的大约10个作业,然后将其链接到连接步骤和下一个模拟中。 (基本上是芹菜弦)然而,我需要能够在这台机器上运行至少20个,最终在一台更强大的机器上运行40个。似乎Redis不允许在结果后端使用足够大的对象让我做除13以外的任何事情。我无法找到改变这种行为的方法。
我目前正在执行以下操作,并且工作正常:
test_a_group = celery.group(test_a(x) for x in ['foo', 'bar'])
test_a_result = rev_group.apply_async(add_to_parent=False)
return = test_b(test_a_result.get())
我宁愿做什么:
return chord(test_a_group, test_b())
第二个适用于小型数据集,但不适用于大型数据集。它给了我一个非冗长的Celery ChordError 104:拒绝连接'大数据。
测试B返回非常小的数据,基本上是传递失败,我只是将组结果传递给B,所以它应该工作,除了我认为整个组被追加到B的结果,以父母的形式,使它太大了。我无法找到如何防止这种情况发生。
第一个效果很好,我会没事的,除了抱怨,说:
[2015-01-04 11:46:58,841:警告/工人-6] /home/cmaclachlan/uriel-venv/local/lib/python2.7/site-packages/celery/result.py:45:
RuntimeWarning:永远不要在任务中调用result.get()! 见http://docs.celeryq.org/en/latest/userguide/tasks.html#task-synchronous-subtasks
在Celery 3.2中,这将导致异常 提出而不是仅仅是一个警告。
warnings.warn(RuntimeWarning(E_WOULDBLOCK))
链接基本上表明我想做什么,但不能。
我想我在某处看到Redis对推送到它的数据大小限制为500 MB。
对这个最毛躁的问题有什么建议吗?
答案 0 :(得分:0)
Celery并非真正意图直接解决这个问题。一般来说,您希望将任务的输入/输出保持较小。
每个输入或输出都必须序列化(默认为pickle)并通过代理传输,例如RabbitMQ或Redis。由于代理需要在没有可用于处理它们的客户端时对消息进行排队,因此最终可能会支付将数据写入/读取到磁盘的命中(至少对于RabbitMQ而言)。
通常,人们在芹菜之外存储大量数据,只需通过URI,ID或其他独特的东西在任务中访问它。常见的解决方案是使用共享网络文件系统(如前所述),数据库,memcached或像S3这样的云存储。
你绝对不应该在任务中调用.get(),因为它可能会导致死锁。