如何使计算循环易于拆分和恢复?

时间:2018-02-02 09:52:27

标签: 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%计算能力)来实现:

for i in range(100):
    if i % 4 != 0:      #  replace != 0 by 1, 2, or 3 for the parallel scripts #2, #3, #4
        continue
    for j in range(100):
        for k in range(100):
            dothejob(i, j, k)

        with open('done.log', 'a+') as f:    # log what has been done
            f.write("%i %i\n" % (i, j))

但我对这种方法有疑问:

  1. 我必须运行python script.py,然后打开script.py,用if i % 4 != 1替换第2行,然后运行python script.py,然后打开script.py,按if i % 4 != 2替换第2行,然后运行python script.py,然后打开script.py,将第2行替换为if i % 4 != 3,然后运行python script.py

  2. 假设循环中断(需要重启计算机,或崩溃或其他任何事情等)。至少我们知道所有(i,j)已经在done.log中完成了(所以我们不需要再从0开始),但是没有简单的方法来恢复工作。 (好的,我们可以打开done.log,解析它,丢弃重启循环时已经完成的(i,j),我开始这样做了 - 但我有一种感觉,以一种肮脏的方式重新发明已经存在的东西)

  3. 我正在寻找一个更好的解决方案(但是例如map/reduce可能对这个小任务来说太过分了,并且在Python中的几行中不容易使用)。

    问题:如何在多个进程之间轻松拆分计算for i in range(100): for j in range(100): for k in range(100): dothejob(i, j, k)并在Python中轻松恢复(例如重启后)?

1 个答案:

答案 0 :(得分:1)

只需使用一系列流程映射产品,例如:

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计算的所有内容:

the_args = it.product(range(100), range(100), range(100))
#skip previously computed 
while True:
    if next(the_args) == (i, j, k):
        break
...

使用las计算值为(i, j, k)元组。