如何用Python将巨大的嵌套循环整齐地划分为8个(或更多)进程?

8 投票
3 回答
3275 浏览
提问于 2025-04-16 20:49

这次我遇到了一个“设计”问题。使用Python,我需要实现一个数学算法,这个算法需要5个参数。为了找到这5个参数的最佳组合,我用了5层嵌套循环来列举所有可能的组合,范围是我设定的。但是,完成这个过程所需的时间超出了我的预期。所以我觉得是时候使用多线程了……

在这些嵌套循环的核心任务中,主要是计算和保存结果。在我现在的代码中,每次计算的结果都会添加到一个列表中,最后程序结束时再把这个列表写入一个文件。

由于我在任何语言中都没有太多多线程的经验,更不用说Python了,我想请教一下,这个问题的结构应该是什么样的。具体来说,如何动态地将计算任务分配给线程,以及线程如何保存结果,最后又如何把所有结果合并成一个文件。我希望线程的数量可以调整。

如果能提供一些代码示例,那将非常有帮助。

非常感谢你的时间,我很感激。

#

第二天更新: 感谢所有有帮助的回答,现在我知道应该使用多进程而不是多线程。我总是把这两个概念搞混,因为我认为如果是多线程的话,操作系统会在有多个处理器时自动使用它们来运行程序。我会找时间今晚亲自尝试一下多进程。

3 个回答

3

假设这是一个计算量很大的问题(所以它主要依赖CPU),在Python中,多线程对你帮助不大,因为有个叫做GIL的东西。

不过,你可以把计算分散到多个进程中,这样就能利用额外的CPU核心。最简单的方法就是使用multiprocessing这个库。

在这个库的文档页面上,有很多关于如何使用multiprocessing的例子。

7

在Python中,多线程并不能解决这个问题,因为Python并不是同时执行多个线程(它主要是用来处理输入输出的并发)。

你应该使用 multiprocessing,或者使用一个更友好的工具,比如joblib

from joblib import Parallel, delayed

# -1 == use all available processors
results = Parallel(n_jobs=-1)(delayed(evaluate)(x) for x in enum_combinations())
print best_of(results)

这里的 enum_combinations 是用来列举你五个参数的所有组合;你可以通过在嵌套循环的底部加一个 yield 来实现。

joblib 会把这些组合分配到多个工作进程中,并且会处理一些负载均衡的问题。

8

你可以试试我写的一个叫jug的库,它可以解决类似的问题。你的代码可能会像下面这样:

from jug import TaskGenerator
evaluate = TaskGenerator(evaluate)

for p0 in [1,2,3]:
    for p1 in xrange(10):
        for p2 in xrange(10,20):
             for p3 in [True, False]:
                for p4 in xrange(100):
                    results.append(evaluate(p0,p1,p2,p3,p4))

现在你可以运行任意数量的进程(如果你有计算机集群的访问权限,甚至可以跨网络运行)。

撰写回答