0

4 コアのラップトップでシリアル並列処理を実行するために、並列 python (pp) パッケージを使用しました。以下は、ジョブを実行するために使用されるスクリプトの簡単な要約です。並列 Python オブジェクトを初期化した後、タスクを 4 つのジョブに分割し、それらをリストに取得しました。

import pp
ppservers = ()
job_server = pp.Server(ppservers = ppservers)

start = 1
end = 1000
parts = 4
step = (end-start)/parts + 1

jobs=[]
for i in xrange(parts):
   starti = pp_start + i * step - 1
   endi = min(pp_start + (i+1)*step - 1,pp_end)
jobs.append(job_server.submit(functionName,(arg1,arg2)))

results=[job() for job in jobs]

私が気付いたのは、for ループのパフォーマンスはかなり高速 (数秒以内) でしたが、取得プロセス (results = [job() for job in jobs]) に時間がかかりすぎたことです (約 10 分)。

誰かがこれがなぜなのかを説明し、この問題を回避する方法を推奨できますか? ありがとうございました。

4

1 に答える 1

0

1000 個のプロセスを生成しているため、1000 個の Python インスタンスを意味します。あなたのような小さな仕事の場合、かなり遅くなります。あなたはこれを望んでいませんpp。さらに悪いことに、ppservers(ローカル プロセスではなく) ネットワークを介している場合、ソケット接続を作成するオーバーヘッドがあるだけでなく、ネットワークを介してコードを送信して別のコンピューターで Python インスタンスを生成するオーバーヘッドもあります( s)。ソケットとインターネット接続を使用したくない場合は、 , をpp設定することで、強制的にローカルでのみ動作させることができますppservers=()(既に行っているようです)。 ppまた、コードをシリアル化し、プロセス間で送信してから、他のプロセスでコード オブジェクトを再構成する必要があります。これも速度を低下させる可能性があります。ソケットをまたいでいる場合や、生成された Python インスタンスでメモリを固定している場合を除き、10 分は期待できません。

ppこの場合の代わりにスレッドを使用することをお勧めしmultiprocessingます-つまり、関数が小さいように見えるため、ライブラリです。

優れた抽象化を提供するライブラリが必要な場合は、コードを変更せずに特定のジョブにデプロイするライブラリppmultiprocessing選択できますpathos。 また、高速化に役立つpathosデフォルトと微調整も提供します。pp次に、どの方法で関数を実行するのが最も速いかをテストし、それを実行できます。

>>> import pathos.pp as pp
>>> import pathos.multiprocessing as mp
>>>    
>>> def squared(x):
...   return x**2
... 
>>> pppool = pp.ParallelPythonPool()
>>> mppool = mp.ProcessingPool()
>>> 
>>> res = pppool.amap(squared, xrange(1000))
>>> sqd = mppool.map(squared, xrange(1000))
>>> sqd[:10], sqd[-10:]
([0, 1, 4, 9, 16, 25, 36, 49, 64, 81], [980100, 982081, 984064, 986049, 988036, 990025, 992016, 994009, 996004, 998001])
>>> 
>>> sq = res.get()
>>> sq[:10], sq[-10:]
([0, 1, 4, 9, 16, 25, 36, 49, 64, 81], [980100, 982081, 984064, 986049, 988036, 990025, 992016, 994009, 996004, 998001])
>>> 
>>> thpool = mp.ThreadingPool()
>>> s = thpool.imap(squared, xrange(1000))
>>> s = list(s)
>>> s[:10], s[-10:]
([0, 1, 4, 9, 16, 25, 36, 49, 64, 81], [980100, 982081, 984064, 986049, 988036, 990025, 992016, 994009, 996004, 998001])

上記では、非同期 (非ブロッキング) マップを使用しmultiprocessingながら、ブロッキング マップを使用しています。ppその後、スレッドでイテレータ マップを実行します (レバレッジmultiprocessing)。ところで、クラスタ スケジューラpathosへの接続も提供します (上記には示されていません)。MPI

pathosここにアクセスしてください: https://github.com/uqfoundation

于 2015-01-19T14:12:55.857 に答える