web-dev-qa-db-ja.com

Python 2.7concurrent.futures.ThreadPoolExecutorは並列化されません

4つの仮想コア(2つのハイパースレッド/物理コア、64ビット)とUbuntu14.04がインストールされたInteli3ベースのマシンで次のコードを実行しています。

n = multiprocessing.cpu_count()
executor = ThreadPoolExecutor(n)
Tuple_mapper = lambda i: (i, func(i))
results = dict(executor.map(Tuple_mapper, range(10)))

CPUは常に25%しか使用されていないため、コードは並列実行されていないようです。使用率グラフでは、4つの仮想コアのうち1つだけが一度に100%使用されます。利用されるコアは約10秒ごとに交互になっています。

ただし、並列化は、同じソフトウェア設定のサーバーマシンでうまく機能します。コアの正確な数やプロセッサの種類はわかりませんが、コアがいくつかあり、使用率が100%であり、計算が高速化されていることは確かです(並列化を使用した後、10倍高速になりました。それを使ったいくつかの実験)。

並列化は、サーバーだけでなく、私のマシンでも機能すると思います。

なぜ機能しないのですか?それは私のオペレーティングシステムの設定と関係がありますか?それらを変更する必要がありますか?

前もって感謝します!

更新:背景情報については、以下の正解を参照してください。完全を期すために、問題を解決したサンプルコードを示します。

Tuple_mapper = lambda i: (i, func(i))
n = multiprocessing.cpu_count()
with concurrent.futures.ProcessPoolExecutor(n) as executor:
    results = dict(executor.map(Tuple_mapper, range(10)))

これを再利用する前に、使用しているすべての関数が、ここで説明するようにモジュールのトップレベルで定義されていることに注意してください。 Pythonマルチプロセッシングピクルスエラー

12
Gerhard Hagerer

Pythonの Global Interpreter Lock (a.k.a GIL)の結果が表示されているようです。

CPythonでは、グローバルインタープリターロック(GIL)は、複数のネイティブスレッドを防止するがPythonバイトコードを一度に実行するのを防ぐ]ミューテックスです。

すべてのスレッドが純粋なPythonコードを実行しているため、実際に並列で実行できるのは1つだけです。これにより、1つのCPUのみがアクティブになり、問題の説明と一致するはずです。

同じモジュールからProcessPoolExecutorで複数のプロセスを使用することで、これを回避できます。他の解決策には、GILを持たないJythonまたはIronPythonへの切り替えが含まれます。

ProcessPoolExecutorクラスは、プロセスのプールを使用して呼び出しを非同期に実行するExecutorサブクラスです。 ProcessPoolExecutorはマルチプロセッシングモジュールを使用しますグローバルインタープリターロックを回避できますだけでなく、選択可能なオブジェクトのみを実行して返すことができることも意味します。

14
kichik