尝试并行化嵌套for循环并保存中间结果
我对并行处理完全是个新手。我想要把一个嵌套的for循环进行并行处理,并存储一些中间结果。这些结果来自一个函数f,这个函数需要一些正式的参数和一些全局变量的值。我在这里得到了些建议,比如我可以使用itertools来生成一个笛卡尔积,这样就相当于一个嵌套循环。但似乎并没有效果。我想存储中间结果的数组没有变化。我附上了一个最小的可工作示例。
操作系统:Windows 7 64位
Python版本:Canopy Enthought
import itertools
import numpy as np
from multiprocessing import Pool
list1 = range(4, 8)
list2 = range(6, 9)
ary = np.zeros( (len(list1), len(list2)) )
#This is the archetypical function f. It DOES NOT have p2 as a parameter! This
#is intended! In my (more complex) program a function f calls somewhere deep
#down another function that gets its values from global variables. Rewriting
#the code to hand down the variables as parameters would turn my code into a mess.
def f(p1):
return p1*p2
#This is what I want to parallelize: a nested loop, where the result of f is saved
#in an array element corresponding to the indices of p1 and p2.
#for p1 in list1:
# for p2 in list2:
# i = list1.index(p1)
# j = list2.index(p2)
# ary[i,j]=f(p1)
#Here begins the try to parallelize the nested loop. The function g calls f and
#does the saving of the results. g takes a tuple x, unpacks it, then calculates
#f and saves the result in an array.
def g(x):
a, b = x
i = list1.index(a)
j = list2.index(b)
global p2
p2 = b
ary[i,j] = f(a)
if __name__ == "__main__":
#Produces a cartesian product. This is equivalent to a nested loop.
it = itertools.product(list1, list2)
pool = Pool(processes=2)
result = pool.map(g, it)
print ary
#Result: ary does not change!
2 个回答
0
你需要通过某种方式在不同的进程之间共享信息。比如可以看看multiprocessing.queue这个东西。
如果你想使用共享内存,那就得用线程(threading)了。虽然全局解释器锁(GIL)会影响线程的性能,但你可能还是能让numpy的命令并行运行。
1
通过使用 Pool
,你的程序会复制出多个进程,每个进程都有自己的全局变量。当你的计算完成后,主进程的全局变量并没有改变。
你应该使用你并行调用的函数的返回值,并把结果结合起来,也就是说,要使用你在代码中提到的 result
变量。
result = pool.map(g, it)
在你的情况下,它目前只包含了一堆 None
。
关于并行计算的一个通用建议是:始终使用纯计算,也就是说,不要依赖像全局变量这样的副作用。