2012-02-20 1 views
6

にforループネストされた:私はそれをスピードアップするために私の4コアマシン上でこのループを並列化したい並列化は、私は次のようになります私のPythonコードでのループの入れ子になっていIPython

results = [] 

for azimuth in azimuths: 
    for zenith in zeniths: 
     # Do various bits of stuff 
     # Eventually get a result 
     results.append(result) 

を。 IPython並列プログラミングのドキュメント(http://ipython.org/ipython-doc/dev/parallel/parallel_multiengine.html#quick-and-easy-parallelism)を見ると、mapを使用して反復を並列化する簡単な方法があるようですオペレーション。

しかし、これを行うには、ループ内のコードを(これは簡単に)関数として用意して、この関数にマップする必要があります。私が持っている問題は、この関数をマップするための配列を取得できないことです。 itertools.product()は、マップ関数を使用することができないイテレータを生成します。

ここで地図を使って間違った木を吠えていますか?それを行うより良い方法はありますか?または、itertools.productを使用して、結果全体にマップされた関数で並列実行を行う方法がありますか?

+0

を使用Clojureののマップ機能は、シーケンス上で動作し、ほとんどのシーケンスは、容器、何を実装することができ、その本当にただのインターフェイスされています。 (鉄)Pythonで利用できるようなものはありますか? – Bill

+0

'itertools.product'を試してみるとどうなりますか?それはそれを行う方法のように見えます。 –

+0

'itertools.product'は、方位角と天頂のすべての組み合わせに対してイテレータを作成するのに適しているようですが、これを並列化することはできません。どのようにこれを行うにはどのようなアイデア? – robintw

答えて

10

すべての呼び出しを並列化するには、各引数のリストを取得するだけです。 、

amr = dview.map(f, allzeniths, allazimuths) 

のステップに少し深く行くためにここに例を示します:次に、あなたはマップを使用することができます

allzeniths, allazimuths = zip(*itertools.product(zeniths, azimuths)) 

:あなたはこれを取得するためにitertools.product + zipを使用することができます

zeniths = range(1,4) 
azimuths = range(6,8) 

product = list(itertools.product(zeniths, azimuths)) 
# [(1, 6), (1, 7), (2, 6), (2, 7), (3, 6), (3, 7)] 

だから私たちは "ペアのリスト"を持っていますが、本当に必要なのは各引数のリストです。つまり、 "リストのペア"です。今、私たちはループの入れ子の並列化、これら二つのリストに私達の機能をマップ

allzeniths, allazimuths = zip(*itertools.product(zeniths, azimuths)) 

print allzeniths 
# (1, 1, 2, 2, 3, 3) 
print allazimuths 
# (6, 7, 6, 7, 6, 7) 

def f(z,a): 
    return z*a 

view.map(f, allzeniths, allazimuths) 

そしてそこにあることについて特別なことは何もありませんこれは少し奇妙zip(*product)構文は、私たちを取得する、まさにです2つだけです。このメソッドは任意の数のネストされたループに拡張する必要があります。

1

私はIPythonに精通していませんが、簡単な解決策は外側のループのみを並列化することです。

def f(azimuth): 
    results = [] 
    for zenith in zeniths: 
     #compute result 
     results.append(result) 
    return results 

allresults = map(f, azimuths) 
8

あなたはIPython 0.11以降を使用していることを前提としています。まず第一に、単純な関数を定義します。

def foo(azimuth, zenith): 
    # Do various bits of stuff 
    # Eventually get a result 
    return result 

次に、IPythonの細かい並列スイートを使用して問題を並列化します。最初の(あなたはIPython 0.11をインストールした場合、後でこのプログラムが存在しなければならない)、ターミナルウィンドウでクラスタを起動して取り付けた5つのエンジン(#CPUs + 1)とコントローラを起動します。あなたのスクリプトで

ipcluster start -n 5 

は、接続すべてのタスクを送信します。コントローラーがすべてを処理します。

from IPython.parallel import Client 

c = Client() # here is where the client establishes the connection 
lv = c.load_balanced_view() # this object represents the engines (workers) 

tasks = [] 
for azimuth in azimuths: 
    for zenith in zeniths: 
     tasks.append(lv.apply(foo, azimuth, zenith)) 

result = [task.get() for task in tasks] # blocks until all results are back 
+0

この例では、定義されていないグローバル結果に関するエラーが発生します。私は複数のプロセッサが結果を見ていないと仮定しています。共有する方法? –

+0

@ john-m私はこれを4年前に書いた。現時点では、IPythonはバージョン0.11でした。彼らは現在4.xにいると私は信じている。私の例は時代遅れかもしれない。私はIPythonを何年も使っていません。 – koloman

1

あなたが実際に並行して、あなたのコードを実行したい場合は、concurrent.futures

import itertools 
import concurrent.futures 

def _work_horse(azimuth, zenith): 
    #DO HEAVY WORK HERE 
    return result 

futures = [] 
with concurrent.futures.ProcessPoolExecutor() as executor: 
    for arg_set in itertools.product(zeniths, azimuths): 
     futures.append(executor.submit(_work_horse, *arg_set)) 
executor.shutdown(wait=True) 

# Will time out after one hour. 
results = [future.result(3600) for future in futures] 
関連する問題