web-dev-qa-db-ja.com

Pythonすべてシングルコアで実行されるスレッド

Python多くのスレッドを生成し、一度に4つのスレッドを実行し、それぞれが高価な操作を実行するプログラムです。擬似コード:

for object in list:
    t = Thread(target=process, args=(object))
    # if fewer than 4 threads are currently running, t.start(). Otherwise, add t to queue

しかし、プログラムを実行すると、OS Xのアクティビティモニターには、4つの論理コアのうち1つが100%で、他のコアがほぼ0になっていることが示されます。以前はこのようなマルチスレッドコードのパフォーマンスに注意を払っていたので、何かが足りないのか、誤解しているのか疑問に思っていました。

ありがとう。

52
Rob Lourens

多くの場合(そして「あなたの「高価な操作」がPythonで実装される計算である事実上すべての場合)、Pythonの Global Interpreter Lock(GIL) のために、複数のスレッドは実際に同時に実行されないことに注意してください。

GILはインタープリターレベルのロックです。このロックは、Pythonインタープリターで複数のスレッドが同時に実行されるのを防ぎます。実行したい各スレッドは、GILが他のスレッドによって解放されるのを待つ必要があります。つまり、マルチスレッドPythonアプリケーションは本質的にシングルスレッドです。はい。ではない正確に。並べ替え。

CPythonは、「オペレーティングシステム」スレッドと呼ばれるものを使用します。つまり、新しいスレッドを作成する要求が行われるたびに、インタープリターは実際にオペレーティングシステムのライブラリとカーネルを呼び出して新しいスレッドを生成します。これは、たとえばJavaと同じです。したがって、メモリには実際に複数のスレッドがあり、通常はオペレーティングシステムが実行するスレッドを制御します。これは、マルチプロセッサマシンでは、多数のスレッドを複数のプロセッサに分散させることができ、すべてのスレッドが喜んで作業を行っていることを意味します。

ただし、CPythonはオペレーティングシステムスレッドを使用しますが(理論上はインタープリター内で複数のスレッドを同時に実行できます)、インタープリターはインタープリターとスタックにアクセスしてPythonメモリー内のオブジェクトはすべて意のままです。後者の点は、GILが存在する理由です。GILは、複数のスレッドによるPythonオブジェクトへの同時アクセスを防ぎます。しかし、これはあなたを(Bankの例で示されているように)ロックに敏感なクリーチャーになることから救いません。自由に乗ることはできません。 GILは、あなたの正気ではなく、通訳者の記憶を保護するためにあります。

詳細については、 Jesse Nollerの投稿 のGlobal Interpreter Lockセクションを参照してください。

この問題を回避するには、 Pythonのマルチプロセッシングモジュール を確認してください。

複数のプロセス(IPCの賢明な使用)は、スレッドよりもマルチCPUボックス用のアプリを作成するためのはるかに優れたアプローチです。

- Guido van Rossum(Pythonの作成者)

68
Gabriel Grant

Pythonには、インタープリターコードのスレッドが同時に処理されるのを防ぐことができるグローバルインタープリターロックがあります。

http://en.wikipedia.org/wiki/Global_Interpreter_Lock

http://wiki.python.org/moin/GlobalInterpreterLock

これを回避する方法については、ここでアドバイスされているように、 multiprocessing module を試してください。

個別に実行pythonプロセスはGILを回避しますか?

9
T.R.

私の知る限り、CPythonのグローバルインタープリターロックは、Pythonコードが同時に実行されるコードのブロックが1つしか存在できないことを意味します。これは、単一のプロセッサ/シングルコアマシン、マルチコアマシンでは、同時に実行されるスレッドは事実上1つだけであり、他のすべてのコアはアイドル状態になります。

2
MAK