97

私は 60GB の SciPy Array (Matrix) を持っており、5 つ以上multiprocessing Processのオブジェクト間で共有する必要があります。numpy-sharedmem を見て、SciPy リストでこのディスカッションを読みました。2つのアプローチがあるようです.anumpy-sharedmemを使用し、multiprocessing.RawArray()NumPydtypeをsにマッピングしctypeます。さて、numpy-sharedmem進むべき道のようですが、良い参考例はまだ見ていません。配列 (実際には行列) は読み取り専用になるため、ロックは必要ありません。サイズが大きいため、コピーは避けたいと思います。配列の唯一のコピーを配列として作成し、それをオブジェクトに渡すのが正しい方法のように思えますか? いくつかの具体的な質問:sharedmemProcess

  1. 共有メモリハンドルを実際にサブに渡す最良の方法は何Process()ですか? 1 つの配列を渡すためだけにキューが必要ですか? パイプの方がいいですか?Process()サブクラスの initに引数として渡すことはできますか?

  2. 上記でリンクしたディスカッションでnumpy-sharedmemは、64 ビットセーフではないという言及がありますか? 私は間違いなく、32 ビットでアドレス指定できない構造をいくつか使用しています。

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

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

  5. これを行うオープンソースコードの例はありますか? 私は非常に実践的な学習者であり、見るべき良い例がなければ、これを機能させるのは困難です。

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

これは Ubuntu Linux と Mac OS で実行する必要があります、移植性は大きな問題ではありません。

4

6 に答える 6

31

@Velimir Mlaker はすばらしい答えをくれました。少しのコメントと小さな例を追加できると思いました。

(sharedmem に関するドキュメントはあまり見つかりませんでした。これらは私自身の実験の結果です。)

  1. サブプロセスの開始時または開始後にハンドルを渡す必要がありますか? 前者だけの場合は、targetとのargs引数をそのまま使用できます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'>

この関連する質問が役立つ場合があります。

于 2013-07-30T15:54:18.030 に答える
16

配列がそれほど大きい場合は、 を使用できますnumpy.memmap。たとえば、ディスクに配列が保存されている場合、たとえば、'test.array'「書き込み」モードでも同時プロセスを使用してその中のデータにアクセスできますが、「読み取り」モードのみが必要なため、ケースはより単純です。

アレイの作成:

a = np.memmap('test.array', dtype='float32', mode='w+', shape=(100000,1000))

その後、通常の配列と同じ方法でこの配列を埋めることができます。例えば:

a[:10,:100]=1.
a[10:,100:]=2.

変数を削除すると、データはディスクに保存されますa

後で、次のデータにアクセスする複数のプロセスを使用できますtest.array

# read-only mode
b = np.memmap('test.array', dtype='float32', mode='r', shape=(100000,1000))

# read and writing mode
c = np.memmap('test.array', dtype='float32', mode='r+', shape=(100000,1000))

関連する回答:

于 2013-07-26T11:26:30.080 に答える
3

また、 pyroのドキュメントを参照すると、タスクを適切に分割でき、同じマシンの異なるコアだけでなく、異なるマシンで異なるセクションを実行するために使用できるため、役立つ場合があります。

于 2013-07-31T05:39:20.120 に答える