Pythonのグローバルインタープリターロックの正確な機能は何ですか?バイトコードにコンパイルされる他の言語も同様のメカニズムを採用していますか?
Pythonのグローバルインタープリターロックの正確な機能は何ですか?バイトコードにコンパイルされる他の言語も同様のメカニズムを採用していますか?
回答:
一般に、スレッドセーフの問題では、内部データ構造をロックで保護する必要があります。これは、さまざまなレベルの粒度で実行できます。
個別の構造ごとに独自のロックがある細粒度ロックを使用できます。
1つのロックですべてを保護する粗粒度ロックを使用できます(GILアプローチ)。
各方法にはさまざまな長所と短所があります。きめの細かいロックにより、並列性が向上します。2つのスレッドがリソースを共有しない場合は、並列で実行できます。ただし、はるかに大きな管理オーバーヘッドがあります。コードのすべての行について、いくつかのロックを取得して解放する必要がある場合があります。
大まかなアプローチはその逆です。2つのスレッドを同時に実行することはできませんが、個々のスレッドは簿記をあまり行わないため、より速く実行されます。最終的には、シングルスレッドの速度と並列処理の間のトレードオフになります。
PythonでGILを削除しようとする試みはいくつかありますが、シングルスレッドマシンの余分なオーバーヘッドは一般に大きすぎます。ロックの競合が原因で、マルチプロセッサマシンでも実際には遅くなる場合があります。
バイトコードにコンパイルされる他の言語も同様のメカニズムを採用していますか?
これはさまざまであり、実装プロパティほど言語プロパティと見なすべきではありません。たとえば、JythonやIronPythonなどのPython実装には、GILアプローチではなく、基盤となるVMのスレッドアプローチが使用されます。さらに、Rubyの次のバージョンは、GILの導入に向かっているようです。
以下は、公式のPython / C APIリファレンスマニュアルからの抜粋です。
Pythonインタープリターは完全にスレッドセーフではありません。マルチスレッドのPythonプログラムをサポートするために、Pythonオブジェクトに安全にアクセスするには、現在のスレッドが保持する必要のあるグローバルロックがあります。ロックがなければ、最も単純な操作でもマルチスレッドプログラムで問題が発生する可能性があります。たとえば、2つのスレッドが同じオブジェクトの参照カウントを同時にインクリメントすると、参照カウントが2回ではなく1回だけ増加することになります。
したがって、グローバルインタープリターロックを取得したスレッドのみがPythonオブジェクトを操作したり、Python / C API関数を呼び出したりできるというルールがあります。マルチスレッドのPythonプログラムをサポートするために、インタプリタは定期的にロックを解放して再取得します-デフォルトでは、100バイトコードの命令ごとに(これはsys.setcheckinterval()で変更できます)。ロックも解放され、ファイルの読み取りや書き込みなどの潜在的にブロックされているI / O操作の周りに再取得されるため、I / Oを要求するスレッドがI / O操作の完了を待機している間に他のスレッドを実行できます。
私はそれが問題をかなりうまくまとめていると思います。
Pythonは、perl 5と同様に、スレッドセーフになるようにゼロから設計されていません。スレッドは事後に移植されたので、グローバルインタープリターロックを使用して、インタープリターの腸内の特定の時間に1つのスレッドのみがコードを実行している場所への相互排除を維持します。
個々のPythonスレッドは、ロックを頻繁に循環させることにより、インタープリター自体によって協調的にマルチタスク化されます。
他のPythonスレッドがこのプロトコルに「オプトイン」するためにアクティブであるときにCからPythonと通信しているときに、自分でロックを取得する必要があります。
後でマルチスレッドシステムに進化したシングルスレッドの遺産を持つ他のシステムは、多くの場合、この種のメカニズムを備えています。たとえば、Linuxカーネルには、初期のSMP時代からの「ビッグカーネルロック」があります。時間の経過とともに、マルチスレッドのパフォーマンスが問題になるにつれて、これらの種類のロックをより小さな部分に分割するか、可能な場合は、それらをロックフリーのアルゴリズムとデータ構造に置き換えて、スループットを最大化する傾向があります。
reiserfs
-私がそれについて知っている唯一の本当の理由)。
2番目の質問に関しては、すべてのスクリプト言語がこれを使用しているわけではありませんが、それはそれらの能力を弱めるだけです。たとえば、Rubyのスレッドは緑色でネイティブではありません。
Pythonでは、スレッドはネイティブであり、GILはそれらが異なるコアで実行されるのを防ぎます。
Perlでは、スレッドはさらに悪化します。それらはインタプリタ全体をコピーするだけで、Pythonのように使用可能になるにはほど遠いです。
BDFLによるこの記事が役立つかもしれません。