在Python中将多个独立的昂贵操作分配到多个核心上

4 投票
2 回答
2680 浏览
提问于 2025-04-17 14:55

假设你有一个很大的列表,里面有超过1000个完全独立的对象,每个对象都需要通过一个耗时的函数来处理,大约需要5分钟。那怎么把这些工作分配到其他处理器上去呢?理论上,我可以把这个列表切成几份,然后用cPickle把数据序列化(这大概需要几秒钟),接着为每一块数据启动一个新的Python进程。如果我打算使用多台电脑,可能真的要这样做,但我觉得这听起来像是个临时的解决办法。难道没有更好的方法可以利用多进程库来实现这个吗?我是不是想太多了?

谢谢。

2 个回答

1

如果你想在一台电脑上运行这个任务,可以使用 multiprocessing.Pool(),这是@Dougal在他的回答中提到的。

如果你想让多台电脑一起解决这个问题,Python也能做到。我在谷歌上搜索了“python并行处理”,找到了这个:

Python中的并行处理

其中一个回答推荐了“mincemeat”,这是一个在单个377行的Python源文件中的map/reduce解决方案!

https://github.com/michaelfairley/mincemeatpy

我敢打赌,只要稍微动动脑筋,你就可以用 multiprocessing.Pool() 来启动一组mincemeat客户端,这样就能在多台电脑上使用多个核心。

补充:我今晚做了一些额外的研究,发现Celery是个不错的选择。Celery可以在每台机器上同时运行多个工作进程。

http://www.celeryproject.org/

Celery在这里被推荐过:

https://stackoverflow.com/questions/8232194/pros-and-cons-of-celery-vs-disco-vs-hadoop-vs-other-distributed-computing-packag

6

这听起来是使用 multiprocessing.Pool 的一个好例子;具体怎么做可能很简单,比如说:

pool = multiprocessing.Pool(num_procs)
results = pool.map(the_function, list_of_objects)
pool.close()

这个方法会把列表中的每个对象单独处理。如果这样做有问题,还有其他方法可以解决这个问题(不过每种方法都有自己的麻烦,我不确定这些方法在Windows上是否有效)。不过,由于你的计算时间比较长,这个问题可能不太重要。

因为你要处理的内容是5分钟乘以1000个项目,这样算下来可能需要几天的时间,具体取决于你的处理器核心数量,所以你可能想在这个过程中保存一些部分结果,并打印出一些进度信息。最简单的方法可能就是让你调用的函数把结果保存到文件、数据库或者其他地方;如果这样不太可行,你也可以在循环中使用apply_async,边处理边获取结果。

你还可以考虑使用类似 joblib 的工具来帮你处理这些事情;我对这个工具不太熟悉,但它似乎也在解决类似的问题。

撰写回答