2013-11-04 3 views
6

多くの同様の質問がありますが、答えは見つかりません。単純な配列には、マルチプロセッシングがあります。配列。スパース行列や他の任意のオブジェクトに対して、私はmanager.namespaceを見つける。そこで以下のコードを試しました:には、Pythonでマルチプロセッシングで読み取り専用の希薄な行列を共有する効率的な方法があります。

from scipy import sparse 
from multiprocessing import Pool 
import multiprocessing 
import functools 

def myfunc(x,ns): 
    return ns.A[x,:]*ns.A*ns.A[:,x] 

manager = multiprocessing.Manager() 
Global = manager.Namespace() 
pool=Pool() 
Global.A=sparse.rand(10000,10000,0.5,'csr') 
myfunc2=functools.partial(myfunc,ns=Global) 
r=pool.map(myfunc2, range(100)) 

コードは機能しますが、効率的ではありません。 16人の労働者のうち4人だけが実際に働いています。その理由は、マネージャーが一度に1人の作業者だけがデータにアクセスできるようにするからです。データは読み込み専用なので、実際にはロックは必要ありません。これを行うより効率的な方法がありますか?

p.s.私はcopy-on-write fork()について話しています。私はそれが何であるかは分かりませんが、うまくいきません。最初にAを生成してPool()を実行すると、各プロセスにAのコピーが作成されます。

ありがとうございます。

+1

'multiprocessing.Manager'の代わりに[sharedmem](https://bitbucket.org/cleemesser/numpy-sharedmem/overview)を試してみてください。好奇心から - どのOSを使用していますか? – unutbu

+0

@unutbuありがとうございます。私は共感を見るつもりです。私はクラスタ上のLinuxのVM上でそれを実行しています – user2727768

答えて

0

名前空間オブジェクトのプロパティは、explicitly assigned toの場合にのみ更新されます。良い説明はhereです。

編集:実装を見ると(multiprocessing/managers.py)、共有メモリを使用していないようです。オブジェクトを漬けて、要求されたらオブジェクトを子に送ります。それはおそらくそれが長くかかる理由です。

CPUがコアを搭載しているよりも多くの人員でプールを作成していますか? (つまり、コンストラクタのprocesses引数を使用します)。これは一般的には良い考えではありません。

他にもいくつか試してみることができます。

  • スパース行列をファイルに書き込み、各ワーカープロセスがファイルを読み取るようにします。 OSによってファイルがバッファキャッシュに格納される可能性があるので、これのパフォーマンスは思うよりもはるかに優れている可能性があります。
  • 可能な改善点は、mmapモジュールを使用してメモリマップファイルを使用することです。
+0

ありがとう。コアは労働者の数に等しい。それは、すべての従業員が共有マトリックスに同時にアクセスしようとしており、1人だけがアクセスを取得するからですか?私はマネージャーがロックを持っているかわからない。たぶん私はmmapを試してください。 – user2727768

+0

@ user2727768更新された回答を参照してください。 –

+0

これは理にかなっています!ありがとうございました – user2727768

関連する問題