2012-04-14 7 views
7

これは、(非常に簡略化した例)ファイン(Pythonの2.6.6、Debianのスクイズを)作品:グローバルな状態の拡散を避けるための、Pythonマルチプロセッシングの代替パターン?

from multiprocessing import Pool 
import numpy as np 

src=None 

def process(row): 
    return np.sum(src[row]) 

def main(): 
    global src 
    src=np.ones((100,100)) 

    pool=Pool(processes=16) 
    rows=pool.map(process,range(100)) 
    print rows 

if __name__ == "__main__": 
    main() 

しかし、悪いグローバル状態を教えられているの年後!

from multiprocessing import Pool 
import numpy as np 

def main(): 
    src=np.ones((100,100)) 

    def process(row): 
     return np.sum(src[row]) 

    pool=Pool(processes=16) 
    rows=pool.map(process,range(100)) 
    print rows 

if __name__ == "__main__": 
    main() 

が、動作しませんもちろんの(何かをpickle化することができませんでしハングアップ):、すべての私の本能は、私は本当にむしろに近い何かを書くことになる私に言っています。

ここでの例は簡単ですが、複数の「プロセス」関数を追加するときには、それぞれが複数の追加入力に依存しています...まあまあそれは30年前にBASICで書かれた何かを連想させるようになります。クラスを使用して少なくとも状態を適切な関数で集計しようとするのは明らかな解決策ですが、実際にはdoesn't seem to be that easyです。

multiprocessing.poolを使用するために推奨されるパターンやスタイルがありますが、パラレルマップしたい各機能をサポートするためにグローバルな状態が広がることはありませんか?

経験豊富な「マルチプロセッシングプロ」はこれにどのように対処していますか?

更新は:ピクルスsrc上記各コール/反復の変動がどのプールのワーカープロセスにフォーク、それをものとほぼ同じ良いものではありませんので、私は、はるかに大きな配列を処理中に実際に興味があることに注意してください。

+0

を単純にpool.map(process、product([src]、range(100)))を実行し、両方の変数をargsとして受け入れるようにプロセス関数を変更しますか?これは非常に非効率的ですか? – luke14free

+0

@ luke14free:はい、それはすべての呼び出しのためのsrc配列をpickleしていました。私は実際には、上記のサンプルコードよりもはるかに大きなデータ/配列に興味があります。プロセスプールでは、プールが作成された時点でどのような状態に設定されていても、ワーカープロセスにフォークされ、 "無償で"読むことができます。そのアイデアは、より小さなマイナーな「制御変数」(例えば、フラグ)状態をグローバルに置くことを避けるのに役立つだろう。 – timday

答えて

5

あなたは常に、オブジェクトが共有状態containeことができ、このような呼び出し可能オブジェクトを渡すことができます。私は経験豊富なマルチプロセッシングプロか何かないんだけど、私はなぜできないかを尋ねてみましょう

from multiprocessing import Pool 
import numpy as np 

class RowProcessor(object): 
    def __init__(self, src): 
     self.__src = src 
    def __call__(self, row): 
     return np.sum(self.__src[row]) 

def main(): 
    src=np.ones((100,100)) 
    p = RowProcessor(src) 

    pool=Pool(processes=16) 
    rows = pool.map(p, range(100)) 
    print rows 

if __name__ == "__main__": 
    main() 
+0

面白そうです...このスタイルに試してみて、報告してください... – timday

+0

Yupは非常にうまくありがとうございます;バイバイグローバル。通常は、何か他のものが現れるかどうかを知るために解決策を受け入れる前に、私はもっと長く待つだろうが、これは完璧です。前にこの問題のクラスを試してみましたが、成功しませんでした。コール可能ですべての違いが生じるようです。 – timday

+2

コール可能なピックルではなく、正方形に戻りますか? –

関連する問題