在python中并行化这些嵌套的for循环

时间:2016-11-06 14:51:47

标签: python parallel-processing nested-loops multiprocess

我有一个多维数组(result),应该由一些嵌套循环填充。函数fun()是一个复杂且耗时的函数。我希望以并行方式填充我的数组元素,这样我就可以使用我所有系统的处理能力。 这是代码:

import numpy as np


def fun(x, y, z):
    # time-consuming computation...
    # ...

    return output


dim1 = 10
dim2 = 20
dim3 = 30

result = np.zeros([dim1, dim2, dim3])

for i in xrange(dim1):
    for j in xrange(dim2):
        for k in xrange(dim3):
            result[i, j, k] = fun(i, j, k)

我的问题是"我可以并行化这段代码吗?如果是,怎么样?"

我使用的是Windows 10 64位和python 2.7。

如果可以的话,请通过更改我的代码来提供解决方案。 谢谢!

3 个答案:

答案 0 :(得分:1)

如果你想要一个更通用的解决方案,利用完全并行执行,那么为什么不使用这样的东西:

>>> import multiprocess as mp
>>> p = mp.Pool()
>>> 
>>> # a time consuming function taking x,y,z,...
>>> def fun(*args):
...   import time
...   time.sleep(.1)
...   return sum(*args)
... 
>>> dim1, dim2, dim3 = 10, 20, 30
>>> import itertools
>>> input = ((i,j,k) for i,j,k in itertools.combinations_with_replacement(xrange(dim3), 3) if i < dim1 and j < dim2)
>>> results = p.map(fun, input)
>>> p.close()
>>> p.join()
>>>
>>> results[:2]
[0, 1]
>>> results[-2:]
[56, 57]

注意我使用multiprocess代替multiprocessing,但这只是为了能够在翻译中工作。

我没有使用numpy.array,但是如果你必须......你可以直接将p.map的输出转储到numpy.array然后修改{ {1}}属性为shape,或者您可以执行以下操作:

shape = (dim1, dim2, dim3)

答案 1 :(得分:0)

一种简单的方法可能是将数组分成几部分并创建一些线程来操作这些部分。例如,从(0,0,0)到(5,10,15)的一个部分和从(5,10,16)到(10,20,30)的其他部分。

您可以使用threading模块并执行此类操作

import numpy as np
import threading as t


def fun(x, y, z):
    # time-consuming computation...
    # ...

    return output


dim1 = 10
dim2 = 20
dim3 = 30

result = np.zeros([dim1, dim2, dim3])
#b - beginning index, e - end index
def work(ib,jb,kb,ie,je,ke):
    for i in xrange(ib,ie):
        for j in xrange(jb,je):
            for k in xrange(kb,ke):
                result[i, j, k] = fun(i, j, k)

 threads = list()
 threads.append(t.Thread(target=work, args(0,0,0,dim1/2,dim2/2,dim3/2))
 threads.append(t.Thread(target=work, args(dim1/2,dim2/2,dim3/2 +1,dim1, dim2, dim3))

 for thread in threads:
     thread.start()

您可以通过某种算法定义这些部分,并动态确定线程数。希望它可以帮助你或者至少给你一些想法。

答案 2 :(得分:0)

以下是针对差异fun(i, j, k)索引并行运行k的代码版本。这是通过使用https://docs.python.org/2/library/multiprocessing.html

在不同进程中运行fun来完成的
import numpy as np
from multiprocessing import Pool


def fun(x, y, z):
    # time-consuming computation...
    # ...

    return output


def fun_wrapper(indices):
    fun(*indices)

if __name__ == '__main__':
    dim1 = 10
    dim2 = 20
    dim3 = 30

    result = np.zeros([dim1, dim2, dim3])

    pool = Pool(processes=8)
    for i in xrange(dim1):
        for j in xrange(dim2):
            result[i, j] = pool.map(fun_wrapper, [(i, j, k) for k in xrange(dim3)])

这不是最优雅的解决方案,但您可以从它开始。只有当fun包含耗时的计算

时,您才会加速