14

256x256x256各要素が行列である Numpy 配列があります。multiprocessingこれらの各行列に対していくつかの計算を行う必要があり、モジュールを使用して速度を上げたいと考えています。

これらの計算の結果は、元の配列の256x256x256要素にある行列の結果を新しい配列[i,j,k]の要素に配置する必要があるため、元の配列と同じように配列に格納する必要があります。[i,j,k]

これを行うには、疑似的な方法で記述できるリストを作成し、[array[i,j,k], (i, j, k)]それを関数に渡して「マルチプロセス」にしたいと考えています。matricesこれが元の配列から抽出されたすべての行列のリストであり、計算を行う関数であると仮定するとmyfunc、コードは次のようになります。

import multiprocessing
import numpy as np
from itertools import izip

def myfunc(finput):
    # Do some calculations...
    ...

    # ... and return the result and the index:
    return (result, finput[1])

# Make indices:
inds = np.rollaxis(np.indices((256, 256, 256)), 0, 4).reshape(-1, 3)

# Make function input from the matrices and the indices:
finput = izip(matrices, inds)

pool = multiprocessing.Pool()
async_results = np.asarray(pool.map_async(myfunc, finput).get(999999))

map_asyncただし、実際にはこの巨大なリストを最初に作成しているようですfinput。私のCPUはあまり機能していませんが、メモリとスワップは数秒で完全に消費されます。これは明らかに私が望んでいるものではありません.

最初に明示的に作成する必要なく、この巨大なリストをマルチプロセッシング関数に渡す方法はありますか? または、この問題を解決する別の方法を知っていますか?

本当にありがとう!:-)

4

3 に答える 3

12

関数が呼び出されるとすぐに、すべてのmultiprocessing.Pool.map*メソッドが反復子を完全に消費します(デモ コード) 。イテレータの map 関数チャンクに一度に 1 つのチャンクを供給するには、以下を使用しますgrouper_nofill

def grouper_nofill(n, iterable):
    '''list(grouper_nofill(3, 'ABCDEFG')) --> [['A', 'B', 'C'], ['D', 'E', 'F'], ['G']]
    '''
    it=iter(iterable)
    def take():
        while 1: yield list(itertools.islice(it,n))
    return iter(take().next,[])

chunksize=256
async_results=[]
for finput in grouper_nofill(chunksize,itertools.izip(matrices, inds)):
    async_results.extend(pool.map_async(myfunc, finput).get())
async_results=np.array(async_results)

PS。pool.map_asyncchunksizeパラメータは何か違うことをします: iterable をチャンクに分割し、各チャンクを を呼び出すワーカー プロセスに渡しますmap(func,chunk)。これにより、終了が速すぎる場合にワーカー プロセスが噛むデータが増える可能性がありますが、呼び出しが発行されfunc(item)た直後にイテレータが完全に消費されるため、この状況では役に立ちません。map_async

于 2011-09-05T11:22:32.040 に答える
2

私もこの問題に遭遇しました。これの代わりに:

res = p.map(func, combinations(arr, select_n))

行う

res = p.imap(func, combinations(arr, select_n))

imap はそれを消費しません!

于 2014-01-14T15:38:44.167 に答える
0

Pool.map_async()作業を複数のワーカーにディスパッチするには、イテラブルの長さを知る必要があります。izipがないため__len__、最初にイテラブルをリストに変換し、発生している大量のメモリ使用量を引き起こします。

izipを使用して独自のスタイルのイテレータを作成することで、これを回避することができます__len__

于 2011-09-05T11:00:03.320 に答える