1. ホーム
  2. python

[解決済み] 読み出し専用の大規模なNumpy配列をマルチプロセスで共有する。

2023-01-23 16:51:19

質問

60GBのSciPyの配列(Matrix)を5人以上で共有しなければなりません。 multiprocessing Process オブジェクトで共有しなければなりません。numpy-sharedmemを見て、読みました。 この議論 を読みました。2つのアプローチがあるようです numpy-sharedmem を使用する方法と multiprocessing.RawArray() とマッピングし、NumPyの dtypectype s. 今は numpy-sharedmem が良いようですが、まだ良い参考例を見たことがありません。配列(実際には行列)は読み取り専用なので、ロックは必要ありません。さて、サイズの関係で、コピーは避けたいところです。それは のように聞こえます。 を作成するのが正しい方法です。 だけです。 として配列のコピーを作成することです。 sharedmem の配列としてコピーし、それを Process オブジェクトに渡すのですか?いくつか具体的な質問があります。

  1. 実際にsharedmemのハンドルをサブの Process() に渡す最良の方法は何でしょうか?一つの配列を渡すためだけにキューが必要なのでしょうか?パイプの方が良いのでしょうか?への引数として渡すだけでいいのでしょうか? Process() サブクラスのinit(ここで私はそれがpickleされると仮定しています)に引数としてそれを渡すことができますか?

  2. 上でリンクしたディスカッションでは numpy-sharedmem は 64 ビットセーフではないのですか?私は間違いなく、32ビットアドレス指定可能ではないいくつかの構造体を使用しています。

  3. のトレードオフはありますか? RawArray() アプローチにトレードオフはありますか?より遅く、よりバグが多いですか?

  4. numpy-sharedmemメソッドにctype-to-dtypeのマッピングは必要ですか?

  5. 誰かこれを行ういくつかのオープンソースコードの例を持っていますか?私は非常に実践的な学習者であり、見るべき良い例のようなものがなければ、これを動作させるのは難しいのです。

他の人のためにこれを明確にするために私が提供できる追加情報があれば、コメントしてください、追加します。ありがとうございます。

これは Ubuntu Linux 上で実行する必要があり たぶん Mac OS で動作する必要がありますが、移植性はそれほど重要ではありません。

どのように解決するのですか?

Velimir Mlakerは素晴らしい回答をくれました。私はいくつかのコメントと小さな例を加えることができると思いました。

(sharedmemに関する多くのドキュメントを見つけることができませんでした。これらは私自身の実験の結果です。)

  1. サブプロセスの開始時にハンドルを渡す必要があるのか、それとも開始後に渡す必要があるのか。もし前者だけなら、単に targetargs の引数は Process . これは、グローバル変数を使用するよりも潜在的に優れています。
  2. リンク先のディスカッション ページから、64 ビット Linux のサポートがしばらく前に sharedmem に追加されたようなので、問題ではないかもしれません。
  3. これはどうでしょう。
  4. いいえ、以下の例を参照してください。

#!/usr/bin/env python
from multiprocessing import Process
import sharedmem
import numpy

def do_work(data, start):
    data[start] = 0;

def split_work(num):
    n = 20
    width  = n/num
    shared = sharedmem.empty(n)
    shared[:] = numpy.random.rand(1, n)[0]
    print "values are %s" % shared

    processes = [Process(target=do_work, args=(shared, i*width)) for i in xrange(num)]
    for p in processes:
        p.start()
    for p in processes:
        p.join()

    print "values are %s" % shared
    print "type is %s" % type(shared[0])

if __name__ == '__main__':
    split_work(4)

出力

values are [ 0.81397784  0.59667692  0.10761908  0.6736734   0.46349645  0.98340718
  0.44056863  0.10701816  0.67167752  0.29158274  0.22242552  0.14273156
  0.34912309  0.43812636  0.58484507  0.81697513  0.57758441  0.4284959
  0.7292129   0.06063283]
values are [ 0.          0.59667692  0.10761908  0.6736734   0.46349645  0.
  0.44056863  0.10701816  0.67167752  0.29158274  0.          0.14273156
  0.34912309  0.43812636  0.58484507  0.          0.57758441  0.4284959
  0.7292129   0.06063283]
type is <type 'numpy.float64'>

これは 関連質問 は役に立つかもしれません。