多次元配列(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)
私の質問は、「このコードを並列化できるかどうか?はいの場合、どのように?」です。
私はWindows1064ビットとpython 2.7を使用しています。
可能であれば、私のコードを変更してソリューションを提供してください。ありがとう!
完全並列実行を利用して、より一般的なソリューションが必要な場合は、次のようなものを使用してみませんか。
_>>> 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)
にするか、次のようにします。
_>>> 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)
_
これは、異なるk
インデックスに対してfun(i, j, 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
に時間のかかる計算が含まれている場合にのみ、速度が向上します。
簡単なアプローチは、配列をセクションに分割し、これらのセクション全体で動作するスレッドを作成することです。たとえば、(0,0,0)から(5,10,15)までの1つのセクションと、(5,10,16)から(10,20,30)までの別のセクション。
threading moduleを使用して、次のようなことを行うことができます
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()
いくつかのアルゴリズムを使用してこれらのセクションを定義し、スレッドの数を動的に決定できます。それがあなたを助けるか、少なくともあなたにいくつかのアイデアを与えることを願っています。