首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >在python中并行化这些嵌套的for循环

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

Stack Overflow用户
提问于 2016-11-06 22:51:47
回答 3查看 11.9K关注 0票数 12

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

代码语言:javascript
运行
复制
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。

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

EN

回答 3

Stack Overflow用户

发布于 2016-12-22 03:23:29

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

代码语言:javascript
运行
复制
>>> 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中,然后将shape属性修改为shape = (dim1, dim2, dim3),也可以这样做:

代码语言:javascript
运行
复制
>>> input = ((i,j,k) for i,j,k in itertools.combinations_with_replacement(xrange(dim3), 3) if i < dim1 and j < dim2)
>>> import numpy as np
>>> results = np.empty(dim1*dim2*dim3)
>>> res = p.imap(fun, input)
>>> for i,r in enumerate(res):
...   results[i] = r
... 
>>> results.shape = (dim1,dim2,dim3)
票数 5
EN

Stack Overflow用户

发布于 2016-11-06 23:55:44

这是一个针对不同k索引并行运行fun(i, j, k)的代码版本。这是通过使用https://docs.python.org/2/library/multiprocessing.html在不同进程中运行fun来完成的

代码语言:javascript
运行
复制
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)])
票数 2
EN

Stack Overflow用户

发布于 2016-11-06 23:35:55

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

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

代码语言:javascript
运行
复制
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()

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

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40450661

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档