Python GILを早期に削除しようとした結果、パフォーマンスが低下しました:なぜですか?


13

Pythonの作成者であるGuido Van Rossumからのこの投稿は、PythonからGILを削除する初期の試みに言及しています。

これは以前に試されましたが、残念な結果が出ました。そのため、自分で多くの努力をすることに消極的です。1999年にGreg Stein(Mark Hammond?と)がPythonのフォーク(1.5と思う)を作成し、GILを削除して、すべての可変データ構造のきめの細かいロックに置き換えました。彼はまた、私が受け入れたグローバルな可変データ構造に関する多くの依存関係を削除するパッチを提出しました。ただし、ベンチマーク後、最速のロックプリミティブ(当時のWindows)を備えたプラットフォームでも、シングルスレッドの実行がほぼ2倍遅くなることが示されました。つまり、2つのCPUで、もう少し作業ができるGILを備えた単一のCPU上よりも、GILなしで行われます。これだけでは不十分で、グレッグのパッチは忘れ去られました。(パフォーマンスに関するGregの記事を参照してください。)

私は実際の結果について議論することはできませんが、なぜこれが起こったのか本当に疑問に思います。おそらく、CPythonからGILを削除することが非常に難しい主な理由は、参照カウントメモリ管理システムのためです。典型的なPythonプログラムは何千回または何百万回も呼び出しPy_INCREFPy_DECREFロックをラップする場合の主要な競合ポイントになります。

しかし、アトミックプリミティブを追加すると、シングルスレッドプログラムの速度が低下する理由がわかりません。各Pythonオブジェクトのrefcount変数がアトミックプリミティブになるようにCPythonを変更したと仮定します。そして、参照カウントをインクリメントする必要がある場合、アトミックインクリメント(フェッチアンドアド命令)を行うだけです。これにより、Pythonの参照カウントがスレッドセーフになり、ロック競合が発生しないため、シングルスレッドアプリケーションのパフォーマンスが低下することはありません。

しかし、悲しいかな、私よりも賢い多くの人が試したり失敗したりしているので、明らかに私はここで何かを見逃しています。この問題の見方の何が問題になっていますか?


1
同期が必要な場所はrefcount操作だけではないことに注意してください。引用文では、「すべての可変データ構造のきめ細かいロック」に言及していますが、これには、すべてのリストおよび辞書オブジェクトに少なくとも相互排他ロックが含まれていると考えられます。また、競合に関係なく、アトミック整数演算は非アトミック等価演算ほど効率的ではないと思いますが、そのソースはありますか?

単に、アトミック操作は非アトミック操作よりも遅いためです。それが単一の命令だからといって、それが内部で些細なことを意味するわけではありません。議論についてはこちらご覧ください
モー14

回答:


9

私はGreg Stein Pythonフォークに慣れていないので、必要に応じて、この比較を投機的な歴史的アナロジーとして無視してください。しかし、これはまさにシングルスレッドからマルチスレッドの実装に移行する多くのインフラストラクチャコードベースの歴史的な経験でした。

1990年代に私が研究したすべてのUnix実装(AIX、DEC OSF / 1、DG / UX、DYNIX、HP-UX、IRIX、Solaris、SVR4、およびSVR4 MP)はすべて、まさにこの種の「よりきめ細かいロック-今では遅い!!」問題。私が従ったDBMS、DB2、Ingres、Informix、Oracle、およびSybaseは、すべて同様に通過しました。

「これらの変更により、シングルスレッドで実行している場合に速度が低下することはありません」と100万回聞いたことがあります。そのように機能することはありません。条件付きでチェックするという単純な行為は、「マルチスレッドを実行していますか?」特に高度にパイプライン化されたCPUでは、実際のオーバーヘッドが追加されます。共有データ構造の整合性を確保するために追加されるアトミック操作と時折のスピンロックは、非常に頻繁に呼び出す必要があり、非常に遅いです。第一世代のロック/同期プリミティブも低速でした。ほとんどの実装チームは、さまざまな場所で必要なインターロック保護に応じて、最終的にいくつかのプリミティブのクラスをさまざまな「強度」で追加します。次に、最初にロックプリミティブをスラップダウンした場所が実際には適切な場所ではないことに気付いたため、見つかったボトルネックを中心にプロファイリング、設計、体系的にロトティルまで。これらの固着点のいくつかは最終的にOSまたはハードウェアアクセラレーションを取得しましたが、その全体の進化には3〜5年かかりました。一方、MPまたはMTのバージョンは、パフォーマンス面でリンプしていました。

それ以外の洗練された開発チームは、このようなスローダウンは基本的に永続的で手に負えない人生の事実であると主張しています。IBMは、競争後少なくとも5年間、AIXをSMP対応にすることを拒否しました。Sybaseは同じ引数のいくつかを使用しました。一部のチームが最終的に登場した唯一の理由は、シングルスレッドのパフォーマンスをCPUレベルで合理的に改善できなくなったことです。彼らはMP / MTに進むか、ますます競争力のない製品を受け入れることを余儀なくされました。

アクティブな並行性はHARDです。そして、それは欺de的です。誰もが「これはそれほど悪くないだろう」と考えて突入します。それから、彼らは流砂を打って、すり抜けなければなりません。少なくとも十数十の有名ブランド、資金の豊富なスマートなチームでこれが起こるのを見てきました。一般に、マルチスレッドを選択してMP / MT製品で「パフォーマンスの観点から本来あるべき場所に戻る」には少なくとも5年かかるように思われました。ほとんどは、シフトを行ってから10年経っても、MP / MTの効率/スケーラビリティを大幅に改善していました。

だから、私の推測では、GvRの支持と支持がなければ、PythonとそのGILの長い間苦労した人はいません。彼らが今日そうするつもりだったとしても、あなたが「すごい!我々は本当にMTハンプを超えている!」と言う前に、それはPython 4.xの時間枠になるでしょう。

おそらく、Pythonとそのランタイムを、他のすべてのステートフルインフラストラクチャソフトウェア(すべての言語ランタイム、オペレーティングシステム、トランザクションモニター、および以前に行ったデータベースマネージャー)から分離する魔法があります。しかし、もしそうなら、それはユニークまたはほぼそうです。GILに相当するものを削除する他のすべての人は、MT-notからMT-hotに到達するために5年以上の懸命で献身的な努力と投資を要しました。


2
+1開発者のかなり小さなチームとマルチスレッドTclを行うには、その種の時間がかかりました。コードはそれ以前はMTセーフでしたが、主にメモリ管理(これは動的言語の非常にホットな領域であると思われます)で厄介なパフォーマンスの問題がありました。しかし、この経験は、最も一般的な用語以外ではPythonに引き継がれません。2つの言語のスレッドモデルは完全に異なります。ただ…スローを期待し、奇妙なバグを期待して…
ドナルドフェローズ

-1

別の野生の仮説:1999年には、Linuxや他のUnicesはfutex(2)http://en.wikipedia.org/wiki/Futex)と現在のようなパフォーマンスの同期をとっていませんでした。これらは2002年頃に登場しました(そして2004年頃に2.6に統合されました)。

すべての組み込みデータ構造を同期する必要があるため、ロックのコストが非常に高くなります。atomicσᶎはすでに、原子操作が安価である必要はないことを指摘しました。


1
これをバックアップするものはありますか?または、これはほとんど推測ですか?

1
GvRの引用は、「最速のロックプリミティブを備えたプラットフォーム(当時のWindows)での」パフォーマンスを説明しているため、Linuxでの低速ロックは関係ありません。
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.