2009-08-04 8 views
32

私は、データのコレクションをつかむPythonアプリケーションを持っており、そのコレクションの各データについて、それはタスクを実行します。タスクには遅延が伴うので、完了には時間がかかります。この遅延のため、後で各データにタスクを実行させたくないので、それらをすべて並行して実行してください。マルチプロセスを使用すべきですか?またはこの操作のためのスレッド化?マルチプロセスまたはPythonでのスレッド化?

私はスレッドを使用しようとしましたが、何らかの問題がありましたが、しばしば実際には実行されないタスクがありました。

+0

"データの収集量"はどれぐらいですか?それが巨大であれば、それぞれのスレッドまたはプロセスを開始したくないかもしれません。 –

+0

通常1、2、または3個のデータ。 – Ryan

+0

@ S.Lott - スレッド/プロセスの数をデータのサイズよりもはるかに小さい数値に制限する方法はありますか? –

答えて

0

CPythonのスレッドモデルを使用しても、ガベージコレクションの処理方法によってスレッドが実際には並列に実行されないため、パフォーマンスが向上しません。マルチプロセスは並列実行を可能にします。明らかにこの場合、並列ジョブを実行するために複数のコアを用意する必要があります。

さらに詳しい情報はthis related questionにあります。

+4

これは当てはまりません。 CやC++のようにパフォーマンスの向上はほとんどありませんが、いくつかの並行処理が行われます。特にI/Oバウンドの場合はスレッドが役立ちます。 – Christopher

+0

私はそれを実現しなかった - 情報のおかげで。外部参照はhttp://mail.python.org/pipermail/python-dev/2008-May/079461.htmlです。このベンチマークでは、記述したI/Oバウンド問題の改善を見ることができます。しかし、CPUバインドの問題は実際に** 2よりもPythonスレッドが1よりも遅く実行されたことを指摘する価値があります!あなたのアプリケーションのプロファイリングが不可欠であるようです。 –

7

小さなデータ収集の場合は、subprocess.Popenでサブプロセスを作成するだけです。

各サブプロセスは、stdinまたはコマンドライン引数から単純にデータを取得し、処理して結果を出力ファイルに書き込むだけです。

サブプロセスがすべて終了(またはタイムアウト)している場合は、出力ファイルをマージするだけです。

非常に単純です。

+3

これは本当に重い解決策です。データを外部プロセスに供給するだけでなく、膨大なオーバーヘッドがあります。 – Christopher

+1

@Christopher。ポイントは単純です。 Unixの世界はこの技術を40年間使ってきました。それは簡単なのでうまく動作します。また、同じバイナリイメージの複数のインスタンスを実行しているので、オーバーヘッドは実際には「大量」ではありません。これはGNU/Linuxによってうまく最適化されています。 –

+8

@ S.Lott:長い間使用されてきたというだけでは、それが良い解決策であるとは限りません。計算上の問題には特に適していません。オーバーヘッドは、プロセス全体の構造のメモリオーバーヘッドと、複数のカーネルトランジションのレイテンシがあるため、「大規模」です。 Pythonマルチプロセッシングモジュールは、サブプロセスのように新しい "プロセス"を実際に作成しません。新しいインタプリタコンテキストを作成します。これは、新しいOSレベルのプロセスを作成するよりはるかに軽量です。 – Christopher

7

Stackless Pythonを調べるとよいでしょう。長い時間がかかる機能を制御できる場合は、stackless.schedule()をそこに投げる(次のコルーチンへの降伏を言います)、そうでない場合はset Stackless to preemptive multitaskingとすることができます。

スタックレスでは、あなたがスレッドを持っていないが、タスクレットまたはgreenlets、本質的に非常に軽量スレッドです。マルチタスキングを手に入れるためのセットアップがほとんどない、かなり良いフレームワークがあるという意味では素晴らしいです。

しかし、標準のPythonライブラリのいくつかを置き換える必要があるため、Stacklessは移植性を妨げます。StacklessはCスタックへの依存を取り除きます。次のユーザーにもStacklessがインストールされている場合は非常に移植性がありますが、まれにそのようになります。

29

あなたが本当にmultiprocessing moduleを使用すると、おそらく最軽量ソリューションで、バインドを計算している場合(メモリ消費と実装の難しさの両方の観点インチ)

あなたがI/Oバウンドしている場合は、threading moduleを使用すると、通常得られますあなた良い結果。スレッドにデータを渡すには、スレッドセーフな記憶域(キューなど)を使用していることを確認してください。または、産卵時にそれらに固有の単一のデータを渡します。

PyPyは、パフォーマンスに焦点を当てています。これには、計算処理に役立つさまざまな機能があります。また、ソフトウェアトランザクションメモリもサポートしていますが、これはまだ製品品質ではありません。約束事は、マルチプロセッシング(これはいくつかの厄介な要件があります)よりも単純な並列または並行メカニズムを使用できるということです。

Stackless Pythonも良いアイデアです。 Stacklessは上記のように移植性の問題があります。 Unladen Swallowは有望でしたが、現在は無効です。Pystonは、スピードに焦点を合わせた別の(未完成の)Python実装です。 PyPyとは異なるアプローチを取っており、より良い(あるいはまったく異なる)スピードアップが得られるかもしれません。

0

あなたが持っているデータを簡単にパーティション分割して分けることができれば、そのパーティションを外部で行い、プログラムのいくつかのプロセスにそれらを供給する必要があるように思えます。 (すなわちスレッドの代わりにいくつかのプロセス)

0

IronPythonはCPythonとは異なり、GILです。あなたがしていることに応じて、それを見る価値があるかもしれません。しかし、あなたのユースケースがマルチプロセッシングモジュールに適しているように思えます。

スタックレスのPythonをお勧めする人には、私はそれについての専門家ではありませんが、彼は実際には並行していないソフトウェア "マルチスレッド"複数のコアに拡張することはできません)。これは、非同期(しかし、まだシングルスレッド、非並列)のアプリケーションを構築するための単なる代替方法です。

9

タスクは順番どおりに実行されますが、あなたは並行して実行される錯覚を持っています。タスクは、ファイルI/Oや接続I/Oに使用する場合、軽量であるために適しています。

複数のプロセスが1つのCPU(またはコア)で実行されるため、プロセスが並行して実行されるため、プールを使用したマルチプロセスが適切なソリューションになる可能性があります。

セットアップマルチは非常に簡単である可能性があります

from multiprocessing import Pool 

def worker(input_item): 
    output = do_some_work() 
    return output 

pool = Pool() # it make one process for each CPU (or core) of your PC. Use "Pool(4)" to force to use 4 processes, for example. 
list_of_results = pool.map(worker, input_list) # Launch all automatically 
+0

同じデータを扱っているすべてのコアは意味しますか? input_listを分割して各チャンクを別のコアに渡すことは可能ですか? – Moj

0

あなたはTwistedを見てみたいことがあります。これは、非同期ネットワークタスク用に設計されています。

関連する問題