Celery在本地系统上的效率与Python多进程一样吗?
我在决定是用Python的多进程库、Celery还是pp来做我的应用时遇到了一些困扰。
我的应用程序对CPU的需求很高,但现在只使用了一个CPU,所以我需要把任务分散到所有可用的CPU上(这让我开始关注Python的多进程库)。不过我听说这个库在需要的时候不能扩展到其他机器上。目前我不确定是否需要多于一台服务器来运行我的代码,但我在考虑在本地运行Celery,这样扩展只需要添加新服务器,而不是像使用多进程那样需要重构代码。
我的问题是:这样的想法对吗?如果最后发现单台服务器的多个核心就能完成我的任务,使用Celery在本地会有什么负面影响(比如性能)吗?还是说更建议使用多进程,然后再慢慢转向其他方案?
谢谢!
附言:这是一个个人学习项目,但我希望有一天能在公司做开发,想学习专业人士是怎么做的。
2 个回答
我刚刚做了一个测试,想看看使用 celery 处理数据时比起 multiprocessing.Pool
和共享数组会增加多少额外的时间。这个测试是对一个大小为 (292, 353, 1652) 的 uint16 数组运行维纳滤波器。两个版本的处理方式是一样的(大致上就是把 292 和 353 的维度除以可用 CPU 数量的平方根)。我试了两种 celery 的版本:一种是发送经过序列化的数据,另一种是在每个工作进程中打开底层的数据文件。
结果是:在我这台有 16 核心的 i7 CPU 上,使用 celery 大约需要 16 秒,而使用 multiprocessing.Pool
和共享数组大约需要 15 秒。我觉得这个差别还挺小的。
如果增加处理的细致程度,差别就明显了(因为 celery 需要传递更多的信息):celery 需要 15 秒,而 multiprocessing.Pool
只需要 12 秒。
需要注意的是,celery 的工作进程在主机上已经在运行,而池中的工作进程是在每次运行时新创建的。我不太确定如何在一开始就启动 multiprocessing pool,因为我在初始化时传递了共享数组:
with closing(Pool(processes=mp.cpu_count(), initializer=poolinit_gen, initargs=(sourcearrays, resarrays))) as p:
而且只有 resarrays 是通过锁来保护的。
其实我从来没有用过Celery,但我用过多进程(multiprocessing)。
Celery似乎有好几种方式来传递消息(任务),包括可以在不同的机器上运行工作进程的方式。所以一个缺点可能是,消息传递的速度可能比多进程慢,但另一方面,你可以把负载分散到其他机器上。
你说得对,多进程只能在一台机器上运行。但另一方面,进程之间的通信可以非常快,比如可以使用共享内存。如果你需要处理非常大的数据量,你可以很方便地从本地磁盘读取和写入数据,只需在进程之间传递文件名就可以了。
我不知道Celery在处理任务失败方面表现得怎么样。比如,任务可能永远无法完成,或者可能崩溃,或者你可能想要在任务没有在特定时间内完成时终止它。如果Celery没有这个功能,我也不清楚添加这个支持会有多难。
多进程本身没有容错能力,但你可以自己构建这个功能,难度不大。