Python--そもそもなぜそれが行われたのか?」
プログラマではないので、なぜそうなるのかわかりません。GILを配置する背後にあるロジックは何でしたか?
Pythonには、CPython、IronPython、RPythonなど、いくつかの実装があります。
それらのいくつかはGILを持っています、いくつかは持っていません。たとえば、CPythonにはGILがあります。
から http://en.wikipedia.org/wiki/Global_Interpreter_Lock
GILを使用してプログラミング言語で記述されたアプリケーションは、個別のプロセスを使用して完全な並列処理を実現するように設計できます。各プロセスには独自のインタープリターがあり、次に独自のGILがあるためです。
GILの利点
Python(CPythonとその他)がGILを使用する理由
CPythonでは、グローバルインタープリターロック(GIL)は、複数のネイティブスレッドが一度に実行することを防ぐミューテックスですPythonバイトコードを一度に実行できません。このロックは、主にCPythonのメモリ管理がスレッドセーフではないために必要です。
GILは、マルチスレッドのCPythonプログラムが特定の状況でマルチプロセッサシステムを十分に活用できないため、物議を醸しています。 I/O、画像処理、NumPy数の計算など、ブロックまたは長時間実行される可能性のある操作は、GILの外部で発生することに注意してください。したがって、GILがボトルネックになるのは、CPythonバイトコードを解釈してGILの内部で多くの時間を費やすマルチスレッドプログラムのみです。
Pythonには、いくつかの理由により、きめ細かなロックとは対照的にGILがあります。
シングルスレッドの場合は高速です。
I/Oバインドプログラムのマルチスレッドの場合は、より高速です。
Cライブラリで計算集中型の作業を行うCPUバウンドプログラムのマルチスレッドの場合は、より高速です。
これにより、C拡張機能を簡単に記述できます。Pythonスレッドの切り替えは、許可する場合を除いて(つまり、Py_BEGIN_ALLOW_THREADSマクロとPy_END_ALLOW_THREADSマクロの間)行われません)。
Cライブラリのラッピングが簡単になります。スレッドセーフについて心配する必要はありません。ライブラリがスレッドセーフでない場合は、呼び出し中にGILをロックしておくだけです。
GILはC拡張によってリリースできます。 Pythonの標準ライブラリは、各ブロックI/O呼び出しに関連するGILをリリースします。したがって、GILはI/Oバウンドサーバーのパフォーマンスに影響を与えません。したがって、プロセス(フォーク)、スレッド、または非同期I/Oを使用してPythonでネットワーキングサーバーを作成できます。GILは邪魔になりません。
CまたはFortranの数値ライブラリは、リリースされたGILを使用して同様に呼び出すことができます。 C拡張機能がFFTの完了を待機している間、インタープリターは他のPythonスレッドを実行します。したがって、この場合も、GILは細粒度ロックよりも簡単で高速です。これにより、 NumPy拡張機能は、可能な場合は常にGILを解放します。
スレッドは通常、ほとんどのサーバープログラムを作成するには不適切な方法です。負荷が低い場合、フォークは簡単です。負荷が高い場合は、非同期I/Oおよびイベント駆動型プログラミング(PythonのTwistedフレームワークを使用するなど)の方が優れています。スレッドを使用する唯一の言い訳は、Windowsにos.forkがないことです。
GILは、純粋なPythonでCPUを集中的に使用する作業を行う場合にのみ問題になります。ここでは、プロセスとメッセージパッシング(mpi4pyなど)を使用して、よりクリーンな設計を得ることができます。 Pythonチーズショップ)には「処理」モジュールもあり、スレッドと同じインターフェイスをプロセスに提供します(つまり、threading.Threadをprocessing.Processに置き換えます)。
スレッドは、GILに関係なくGUIの応答性を維持するために使用できます。 GILがパフォーマンスを損なう場合(上記の説明を参照)、スレッドにプロセスを生成させ、プロセスが完了するまで待つことができます。
まず、PythonにはGILがありません。Pythonはプログラミング言語です。プログラミング言語は、抽象的な数学的なルールと制限のセットです。 Python言語仕様には、GILがなければならないという記述はありません。
Pythonには多くの異なる実装があります。 GILがあるものもないものもあります。
GILを使用するための簡単な説明の1つは、並行コードの作成が難しいことです。コードの周りに巨大なロックを配置することで、コードを常に逐次実行するように強制します。問題が解決しました!
特にCPythonでの重要な目標の1つは、Cで記述されたプラグインを使用してインタープリターを簡単に拡張できるようにすることです。ここでも、並行コードの作成は難しいため、並行性がないことを保証することで、拡張機能を簡単に作成できます。通訳。さらに、これらの拡張機能の多くは、既存のライブラリの薄いラッパーであり、並行性を考慮して書かれていない可能性があります。
GILの目的は何ですか?
CAPIのドキュメントでは、これについて次のように述べています。
Pythonインタープリターは完全にスレッドセーフではありません。マルチスレッドのPythonプログラムをサポートするために、グローバルインタープリターロックまたはGILと呼ばれるグローバルロックがあります。 Pythonオブジェクトに安全にアクセスするには、現在のスレッドが保持している必要があります。ロックがないと、最も単純な操作でもマルチスレッドプログラムで問題が発生する可能性があります。たとえば、2つのスレッドが同じオブジェクトの参照カウントを同時にインクリメントすると、参照カウントが2回ではなく1回だけインクリメントされることになります。
つまり、GILは状態の破損を防止します。 Pythonプログラムでは、メモリセーフな操作のみが許可されているため、セグメンテーション違反は発生しません。GILは、この保証をマルチスレッドプログラムに拡張します。
代替案は何ですか?
GILの目的が国家を腐敗から保護することである場合、1つの明白な代替策は、はるかに細かい粒度でロックすることです。おそらくオブジェクトごとのレベルで。これの問題は、マルチスレッドプログラムのパフォーマンスを向上させることが実証されていますが、オーバーヘッドが大きくなり、結果としてシングルスレッドプログラムが影響を受けることです。