Python 如何使计算循环易于拆分和恢复?
对于给定的计算问题,我想在0..99中找到最佳参数Python 如何使计算循环易于拆分和恢复?,python,loops,multiprocessing,computation,Python,Loops,Multiprocessing,Computation,对于给定的计算问题,我想在0..99中找到最佳参数I,j,k,我需要运行: for i in range(100): for j in range(100): for k in range(100): dothejob(i, j, k) # 1 second per computation 这总共需要10^6秒,即11.5天 我开始将工作分为4个进程(使用我的4核CPU计算机的100%计算能力): 但我对这种方法有问题: 我必须运行pyth
I,j,k
,我需要运行:
for i in range(100):
for j in range(100):
for k in range(100):
dothejob(i, j, k) # 1 second per computation
这总共需要10^6秒,即11.5天
我开始将工作分为4个进程(使用我的4核CPU计算机的100%计算能力):
但我对这种方法有问题:
python script.py
,然后打开script.py
,如果我%4!=1,然后运行python script.py
,然后打开script.py
,如果i%4!=2,然后运行python script.py
,然后打开script.py
,如果i%4!=3,然后运行python script.py
done.log
中已经完成的所有(i,j)(因此我们不需要再次从0开始),但是没有简单的方法来恢复工作。(好的,我们可以打开done.log
,解析它,丢弃在重新启动循环时已经完成的(i,j),我开始这样做了——但我有种感觉,要用一种肮脏的方式重新创造一些已经存在的东西)问题:如何对范围(100)中的i进行计算
:范围(100)中的j:范围(100)中的k:dothejob(i,j,k)
在Python中可以在多个进程之间轻松拆分,也可以轻松恢复(例如重新启动后)?只需使用一个进程池映射产品,例如:
import itertools as it
from multiprocessing import Pool
the_args = it.product(range(100), range(100), range(100))
pool = Pool(4)
def jobWrapper(args): #we need this to unpack the (i, j, k) tuple
return dothejob(*args)
res = pool.map(jobWrapper, the_args)
如果您想从日志中了解las(i,j,k)
,只需跳过先前从参数中计算的所有值即可:
the_args = it.product(range(100), range(100), range(100))
#skip previously computed
while True:
if next(the_args) == (i, j, k):
break
...
作为
(i,j,k)
具有las计算值的元组。不阅读所有问题:是否有结果可以在某个点缓存和重用?@rockstaid:没有。每个具有新i,j,k的计算都是一个全新的任务,不能重用过去工作中的任何内容。你不能像这里这样使用并行for循环吗@Basj对于自动拆分和任务管理,请查看上面提到的库。然而,这仍然假设存在一个“管理者”流程,在工人身上生成任务。如果你的管理器死机,或者电脑重新启动,你必须考虑从磁盘加载最后一个已知的状态(这正是解析所要做的…)。如果你需要某种持久性,可以在重新启动后生存下来,那么我首先要做的最简单的事情就是类似sqlite的东西。这将使循环更加复杂,您必须首先检查数据库以查看是否执行了特定的计算。但是这已经比解析日志文件要好了,而且如果你正确地执行数据库模式和查询,速度会更快!好奇:会不会it.product(范围(1000)、范围(1000)、范围(1000))
在内存中创建一个包含10亿项的列表?你对#2:如何暂停/恢复计算有什么想法?或者甚至停止并重新启动计算机,然后继续?您可以通过参数将与i、j、k相关的最后3个计算值传递给脚本,并使用产品迭代器,直到在开始计算之前找到它stuff@Basj,itertools创建了一个迭代器,因此它不会用这些项加载内存,而是按如下方式计算它们needed@Basj,然后,不要在开始时写日志,只要在作业完成时记录日志即可。
the_args = it.product(range(100), range(100), range(100))
#skip previously computed
while True:
if next(the_args) == (i, j, k):
break
...