2012-01-06 13 views
7

これは一部の人にとっては単純すぎるとは申し訳ありませんが、私はまだPythonのマルチプロセッシングでそのトリックを得ていません。私は読んだ
http://docs.python.org/dev/library/multiprocessing
と他の多くのチュートリアルと例を私がGoogleに与えてくれた...それらの多くもここからです。並列処理のためのPythonマルチプロセッシング

私の状況は、多くのnumpy行列を計算する必要があり、後でそれらをnumpy行列に格納する必要があるということです。私は20コアを使用したいとします(または20コアを使用することができます)が、プールリソースが正常に使用されなかったとします。だから私はこのような何か行う上で考えた:

from multiprocessing import Process, Queue 
import numpy as np 

def f(q,i): 
    q.put(np.zeros((4,4))) 

if __name__ == '__main__': 
    q = Queue() 
    for i in range(30): 
      p = Process(target=f, args=(q,)) 
      p.start() 
      p.join() 
    result = q.get() 
    while q.empty() == False: 
      result += q.get() 
    print result 

をしかし、それは並列で実行していないプロセスのように見えますが、彼らは順番に実行します(私が間違っている場合は、私を修正してください)、私はかどうかを知りません彼らは彼らの計算をした後に死ぬ(20以上のプロセスのために、彼らの部分をしたものはコアを別のプロセスのために自由にしておく)。さらに、非常に大きな数値(100.000としましょう)では、待ち行列にすべての行列(実際には大きすぎる可能性があります)を格納すると大量のメモリが使用され、各繰り返しごとにすべての結果を入れることになるため、最後の結果では、ロック(およびそのacquire()メソッドとrelease()メソッド)を使用するのと同じですが、このコードが並列処理用でない場合、ロックは役に立たない...

誰かが助けてくれることを願っています私。

ありがとうございます!

答えて

14

あなたは正しいです、彼らはあなたの例で逐次実行しています。

p.join()は、実行が終了するまで現在のスレッドをブロックします。 forループの外側に個別にプロセスを参加させたい場合(例えば、リストに格納して反復するなど)、numpy.Poolapply_asyncのようなものをコールバックで使用します。これにより、オブジェクトを保持するのではなく、結果に直接追加することもできます。例えば

def f(i): 
    return i*np.identity(4) 

if __name__ == '__main__': 
    p=Pool(5) 
    result = np.zeros((4,4)) 
    def adder(value): 
     global result 
     result += value 

    for i in range(30): 
     p.apply_async(f, args=(i,), callback=adder) 
    p.close() 
    p.join() 
    print result 

クローズした後、端部でプールを結合は、プールの処理が完了していることを保証し、result目的は、計算され終了します。また、問題の解決策としてPool.imapを使用して調査することもできます。

if __name__ == '__main__': 
    p=Pool(5) 
    result = np.zeros((4,4)) 

    im = p.imap_unordered(f, range(30), chunksize=5) 

    for x in im: 
     result += x 

    print result 

これはあなたの特定の状況のた​​めのクリーナーですが、最終的にやろうとしているものは何でものためではないかもしれない:その特定のソリューションは、次のようになります。

あなたの質問が分かっている場合は、コールバックメソッド(上記)またはアイテムごとに/imap_unorderedを使用して結果を追加することができますそれでも結果は保存されますが、ビルド時にクリアされます)。その後、結果に追加するよりも長い間格納する必要はありません。

+0

あなたの答えをありがとう!私は最初の解決策をもっと理解しており、imap_unorderedはすべての結果を保存しているようで、メモリを食べないようにしたいとは思いませんので、コールバックが非常に役立つことがわかります。プールについては、「x」プロセッサーを使用すると、「x」プロセッサーが最初のプロセスが終了しないため、「3x」プロセスが実行されることはわかりません(maxtasksperchild属性について読んでいるため)。私はまた、最初の "x"プロセスのために割り当てられたメモリがコールバックの後に空いているかどうかもわかりません。私は多くのより大きな行列を使用するときに私のPCを単にブロックしないように頼んでいます。 – Carlos

+0

ああ!私は今それを得ると思います:プールは生きている限り労働者は生きていますが、1つのプロセスを終了するとリソースを解放し、次のプロセスを実行して計算を行います。 – Carlos

+0

うん、そうだよ。あなたが実際にそれが問題であることを示すプロファイリングデータを持っていない限り、私は 'Pool'や代替物を心配する必要はありません。できる最適化はありますが、実際のシステムに問題があることをデモンストレーションするまでは、そのほとんどが問題にならないほどです。 –

関連する問題