2

私の質問は、Pythonのマルチプロセッシングモジュールに関するものです。最も単純な形式では、私の質問は次のコードの奇妙な動作です。

import numpy as np
from multiprocessing import Pool

x = np.random.random(100)
y = np.random.random(100)
y2 = y[:]

def I(i):
    y[i] = x[i]

pool = Pool()
pool.map(I,range(100))

実行後、私の希望はy=xです。ただし、y=y2になります。(割り当ては機能していません。)なぜこれが起こっているのですか?f(x [i])を計算してy [i]に割り当てる最良の方法は何ですか?

4

1 に答える 1

1

作業を行うために使用されるプロセス間で何が同期されているかを考えると、表示されている動作はそれほど驚くべきものではありPoolません。関数の引数と戻り値のみが現在のコードで同期されるため、呼び出しプロセスで元の値を保持Iすることは理にかなっています。xy

現在のコードは最小限のテストケースだと思います。これは、を使用して1つの配列を別の配列にコピーするという意味のある実装が実際にはないため、面倒ですPool.map。これは簡単な解決策ですが、実際のタスクが何であれ、それが一般化されるかどうかはわかりません。

import numpy as np
from multiprocessing import Pool

def I(v):
    return v

if __name__ == "__main__":  # this boilerplate is required on on Windows
    x = np.random.random(100)
    y = np.random.random(100)

    pool = Pool()
    y[:] = pool.map(I, x)

    print(x == y) # [True, True, True, ...]

これにより、の各値がx別のプロセスに渡され(何も行われない場合)、結果の値が返され、に割り当てられyます(pool.mapはリストを返します)。それはかなりばかげています。

もう少し洗練されたアプローチでは、コンストラクターで引数と引数xを使用して、ワーカープロセスにコピーすることができます。これを行う例を次に示します。initializerinitargsPool

import numpy as np
from multiprocessing import Pool

def I(index):
    return x[index]

def setup(value):
    global x
    x = value

if __name__ == "__main__":
    x = np.random.random(100)
    y = np.random.random(100)

    pool = Pool(initializer=setup, initargs=(x,))
    y[:] = pool.map(I, range(100))

    print(x == y) # [True, True, True, ...]

ただし、これxは一方向にのみコピーされることに注意してください。その値Iを変更した場合、変更はプロセス間で同期されません。

タスクが実際にソース配列とターゲット配列の両方への同期アクセスを必要とするものである場合は、試してみてくださいmultiprocessing.Array。私はそれを直接経験したことはありませんが、yそれ自体の同期バージョンに置き換えることは可能であるはずです。残念ながら、同期によってプログラムの速度が低下する可能性があるため、本当に必要な場合を除いて、同期を行わないでください。

于 2013-01-09T01:58:35.797 に答える