Python(および他の動的言語)のどのセマンティック機能がその速度低下に寄与していますか?


26

私はPythonをよく知りません。動的言語(Python、Lua、Scheme、Perl、Rubyなど)の正確な機能が実装を強制的に遅らせていることを、より正確に理解しようとしています。

その一例として、Lua 5.3 メタテーブル機構は直感的にLuaを非常に遅くしますが、実際にはLuaは非常に高速(およびPythonよりも高速)であると噂されています。

また、私は現在のプロセッサ上のため、メモリがはるかに遅い生の計算よりであることを直感(おそらく間違ったものを)持っているラà、動的な型チェック((キャッシュミスでメモリアクセスが算術演算の何百ものと同じ時間が必要)if (value->type != INTEGER_TAG) return;でCの用語)は非常に高速に実行できます。

もちろん、プログラム全体の分析(スターリンスキームの実装のように)は、翻訳者が高速で実行されるため、動的言語の実装を行うことができますが、最初はプログラムアナライザー全体を設計する時間がないふりをしましょう。

(私はMELTモニターで動的言語を設計するようなもので、その一部はCに翻訳されます)



1
Luaパフォーマンスのヒント。これは、一部のLuaプログラムが遅い理由とその修正方法を説明しています。
ロバートハーベイ

回答:


24

Python(および他の動的言語)のどのセマンティック機能がその速度低下に寄与していますか?

なし。

言語実装のパフォーマンスは、言語機能ではなく、お金、リソース、および博士論文の機能です。SelfはSmalltalkよりもはるかに動的で、Python、Ruby、ECMAScript、またはLuaよりもわずかに動的であり、既存のすべてのLispおよびSmalltalk VMよりも優れたVMを備えていました(実際、SelfディストリビューションにはSelfで書かれた小さなSmalltalkインタープリターが付属しています) 、さらには既存のほとんどのSmalltalk VMよりも高速でした)、当時のC ++実装と競争力があり、場合によってはさらに高速でした。

その後、SunはSelfへの資金提供を停止し、IBM、Microsoft、Intel、およびCo.はC ++への資金提供を開始し、傾向は逆転しました。Selfの開発者はSunを離れて自社を設立し、Self VM向けに開発されたテクノロジーを使用して史上最速のSmalltalk VM(Animorphic VM)の1つを構築し、Sunはその会社とそのSmalltalk VMは、「HotSpot JVM」という名前で知られるようになりました。皮肉なことに、Javaプログラマーは動的な言語を「遅い」と見なしていますが、実際にはJava動的言語技術を採用するまで遅かった。(はい、そうです。HotSpotJVMは本質的にSmalltalk VMです。バイトコード検証は多くの型チェックを行いますが、バイトコードが検証によって受け入れられると、VM、特にオプティマイザーとJITは実際には行いません。静的型に大きな関心が!)

CPythonは、動的コンパイル(JIT)、動的最適化、投機的インライン化、適応最適化、動的非最適化、動的型フィードバック/推論など、動的言語(または動的ディスパッチ)を高速化する多くの機能を実行しません。また、コアと標準ライブラリのほぼ全体がCで記述されているという問題もあります。つまり、Pythonを突然100倍高速化しても、あまり役に立たないということです。 PythonプログラムはCであり、Pythonではありません。すべてがPythonで記述されている場合、適度なスピードアップでも雪崩効果が発生し、アルゴリズムが高速になり、コアデータ構造が高速になりますが、もちろんコアデータ構造もアルゴリズム内で使用され、コアアルゴリズムとコアデータも使用されます構造は他のあらゆる場所で使用され、

今日のシステムでは、メモリ管理されたオブジェクト指向言語に悪名高い(動的またはそうでない)ものがいくつかあります。仮想メモリとメモリ保護は、特にガベージコレクションのパフォーマンス、および一般的なシステムパフォーマンスのキラーになる可能性があります。また、メモリセーフな言語では完全に不要です。最初に言語にメモリアクセスがない場合に、不正なメモリアクセスから保護するのはなぜですか。Azulは現代の強力なMMU(Intel Nehalem以降、AMDの同等物)を使用して、ガベージコレクションを妨げるのではなく、ガベージコレクションを支援することを考え出しましたが、CPUによってサポートされているにもかかわらず、メインストリームOSの現在のメモリサブシステムは十分に強力ではありませんアズールのJVMが実際にベアメタル上で仮想化走る理由である(これを可能にするほか OS、その中にない)。

Singularity OSプロジェクトでは、Microsoftは、プロセス分離に型システムの代わりにMMU保護を使用した場合、システムパフォーマンスに対する〜30%の影響を測定しました。

特殊なJava CPUを構築するときにAzulが気づいたもう1つのことは、キャッシュミスのコストを削減しようとするとき、現代の主流のCPUは完全に間違ったものに焦点を当てていることです:ブランチ予測、メモリプリフェッチ、等々。しかし、非常に多態的なオブジェクト指向プログラムでは、アクセスパターンは基本的に擬似ランダムであり、単に予測するものはありません。そのため、これらのトランジスタはすべて無駄になっており、代わりに行うべきことは、個々のキャッシュミスのコストを削減することです。(合計コストは#misses *コストで、メインストリームは最初のダウンを試み、Azulは2番目のダウンを試みます。)AzulのJava Compute Acceleratorsは、20000の同時キャッシュミスを飛行し、進行する可能性があります。

アズールが開始すると、彼らは考えた彼らはいくつかの既製のI / Oコンポーネントを取り、自分の専門のCPUコアを設計するだろうが、彼らが実際に終わっ必要が行うには正反対だった:彼らはむしろ標準のオフ・ザを取りましたシェルフ3アドレスRISCコアを設計し、独自のメモリコントローラー、MMU、およびキャッシュサブシステムを設計しました。

tl; dr:Pythonの「スローネス」は言語のプロパティではなく、a)その素朴な(プライマリ)実装、およびb)最新のCPUとOSがCを高速に実行するように特別に設計されているという事実、およびそれらの機能have for CはPythonのパフォーマンスを助けていない(キャッシュ)か、積極的に傷つけています(仮想メモリ)。

動的アドホックポリモーフィズムを使用して、ほとんどすべてのメモリ管理言語をここに挿入できます。効率的な実装の課題に関しては、PythonとJavaでさえ「ほぼ同じ言語」です。


Azulのリンクまたはリファレンスはありますか?
バジルStarynkevitch 16

4
言語のセマンティクスが効率的に実装される能力に影響を与えないことに同意しません。はい、ファーストクラスの最適化と解析との良好なJITの実装では作ることができる広大な言語のパフォーマンスに改善したが、最終的に不可避的なボトルネックになってしまうでしょうセマンティクスの特定の側面があります。ポインターの厳密なエイリアシングに対するCの要件であろうと、リスト操作がアトミックに実行されるというPythonの要件であろうと、ある種のアプリケーションのパフォーマンスを損なうことは避けられない特定のセマンティック決定があります。
ジュール

1
余談ですが、特異点の30%の改善に関する参考資料はありますか?私は長年にわたって言語ベースの保護OSを提唱してきましたが、以前はその数字を見たことがなく、非常に驚​​くべきものでした(過去に見た数字は10%に近かったのです)彼らはそれほど多くの改善を得るため
ジュール

5
@MasonWheeler:くだらないPython実装しか存在しないからです。IBM、Sun、Oracle、Google、およびCo.がJ9、JRockit、HotSpot、およびCoに費やしたお金、人、研究、およびリソースのごくわずかでもPythonの実装者が費やしたことはありません。 Oracleがガベージコレクターだけに費やしている人材を確保してください。IBMは、Eclipse OMR(J9から抽出されたコンポーネント化オープンソースVMのフレームワーク)に基づいて、Python実装に取り組んでいる、私はその性能はJ9の大きさのオーダー内に十分だろうという賭けに喜ん
イェルクWミッターク

2
レコードの場合、Fortranは厳密なエイリアスを強制し、オプティマイザーがより積極的になるため、数値処理用のFortranと比較してCは低速です。
マイケルショップシン16

8

Pythonの現在の実装(他の動的言語、たとえば、最新のJavascript実装、および指摘したようにLuaによって実行される最適化の多くが欠けている)は、その問題のほとんどの原因ですが、少なくとも特定の分野では、実装が他の言語と競合することは困難です。特に考慮に値するもの:

  • リストおよびディクショナリ操作は、言語定義がアトミックであるために必要です。これは、JITコンパイラがリストオブジェクトへの参照が現在のスレッドをエスケープしていないことを証明できない場合(多くの場合困難で一般的なケースでは不可能な分析)、オブジェクトへのアクセスがシリアル化されることを保証する必要があることを意味しますロックを介して)。CPython実装は、悪名高い「グローバルインタープリターロック」を使用してこの問題を解決します。これにより、マルチスレッド環境でのマルチプロセッシング環境でPythonコードが効果的に使用されなくなります。

  • Pythonには、値オブジェクトの使用を指定するメカニズムがありません。すべてが参照によって処理され、必ずしも必要ではない場所に追加の間接性が追加されます。JITコンパイラーは値オブジェクトを推測してこれを自動的に最適化することもできますが、一般的にそうすることは不可能であるため、最適化を保証するために慎重に記述されていないコード(ある程度は黒人の芸術です)苦しむでしょう。

  • Pythonにはeval関数があります。つまり、JITコンパイラーは、eval一度使用される限り、プログラム全体の分析を実行しても、アクションが発生しないという仮定を立てることはできません。たとえば、Pythonコンパイラは、クラスにサブクラスがないと想定できないため、メソッド呼び出しを非仮想化できます。これは、その呼び出しがを呼び出すことで後で無効になる可能性があるためですeval。代わりに、動的な型チェックを実行して、ネイティブにコンパイルされたコードによって行われた仮定がそのコードの実行前に無効にされていないことを確認する必要があります。


3
後者の点はeval、再コンパイルや最適化解除をトリガーすることで軽減できます。
ヨルグWミットタグ

4
ちなみに、これもPythonに固有のものではありません。Java(またはJVM)には動的コードのロードと動的リンクがあるため、クラス階層分析はそこでホールト問題を解決することと同等です。それでも、HotSpotは喜んで投機的に多相メソッドをインライン化します。クラス階層内の何かが変更された場合は、インライン化を解除します。
ヨルグWミットタグ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.