私はPythonをよく知りません。私は動的言語(Python、Lua、Scheme、Perl、Rubyなど)の正確な機能が実装を遅くしていることをより正確に理解しようとしています。
適例として、Lua 5.3 メタテーブルマシナリー は直感的にLuaをかなり遅くしますが、実際にはLuaはかなり高速であると噂されています(Python is)より高速です) 。
また、私は直感(おそらく間違ったもの)を持っています。これは、現在のプロセッサではメモリがraw計算よりもはるかに遅いため(キャッシュミスのあるメモリアクセスには数百の算術演算と同じ時間が必要です)、動的型チェック(àla if (value->type != INTEGER_TAG) return;
)は非常に高速に実行できます。
もちろん、プログラム全体の分析( Stalin Scheme 実装が実行中)は、翻訳者が高速で実行するときに動的言語の実装を作成できますが、最初にプログラムアナライザー全体を設計する時間がないとしましょう。
(私は私の MELTモニター で動的言語を設計するようなものであり、その一部はCに翻訳されます)
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の1つ(Animorphic VM)を構築し、Sunがその会社を買収しました。そして、Smalltalk VMのわずかに変更されたバージョンは、「HotSpot JVM」の名前でよく知られています。皮肉なことに、Javaのプログラマーは動的言語を "遅い"と見なし、実際にはJavaは動的言語テクノロジを採用するまで遅くなりました。 (はい、そうです。HotSpotJVMは基本的にSmalltalk VMです。バイトコード検証は多くの型チェックを行いますが、バイトコードが検証によって受け入れられると、VM、特にオプティマイザとJITは実際には行いません静的型に非常に関心があります!)
CPythonは、動的言語(または動的ディスパッチ)を高速にする多くのこと、つまり動的コンパイル(JIT)、動的最適化、投機的インライン化、適応最適化、動的非最適化、動的型フィードバック/推論を行いません。コアと標準ライブラリのほぼ全体がCで書かれているという問題もあります。つまり、Pythonを突然100倍高速にしても、95のようなものはあまり役に立たないということです。 Pythonプログラムによって実行されるコードの%は、PythonではなくCです。すべてがPythonで記述されている場合、中程度のスピードアップでも雪崩のような影響が生じ、アルゴリズムが高速になり、コアデータ構造が高速になりますが、もちろんコアデータ構造もアルゴリズム内で使用され、コアアルゴリズムとコアデータも使用されます構造は他のあらゆる場所で使用され、以下同様に…
今日のシステムには、メモリ管理されたOO言語(動的または非動的)にとって悪名高い悪名がいくつかあります。仮想メモリとメモリ保護は、ガベージコレクションのパフォーマンス、特にシステムパフォーマンス全般にとってキラーになる可能性があります。また、メモリセーフな言語ではまったく不要です。そもそも言語でメモリアクセスがないのに、なぜ不正なメモリアクセスから保護するのでしょうか。 Azulはhelpガベージコレクションを妨害する代わりに、最新の強力なMMU(Intel Nehalem以降およびAMDの同等のもの)を使用することを考え出しましたが、CPUによってサポートされていますが、現在のメモリサブシステムメインストリームOSはこれを可能にするほど強力ではありません(これが、AzulのJVMが実際にベアメタル上で仮想化されて実行される理由ですbesides OS内ではなく)。
Singularity OSプロジェクトでは、プロセス分離にタイプシステムの代わりにMMU保護を使用した場合、Microsoftはシステムパフォーマンスに最大30%の影響を測定しました。
特殊なJava CPUを構築する際にAzulが気付いたもう1つの点は、キャッシュミスのコストを削減しようとするときに、現代の主流のCPUが完全に間違っていることに焦点を当てていることです。分岐予測、メモリのプリフェッチなど。しかし、多態性の高いOOプログラムでは、アクセスパターンは基本的に疑似ランダムであり、予測するものはありません。したがって、これらのトランジスタはすべて無駄になり、代わりに個々のキャッシュミスのコストを削減する必要があります。 (合計コストは#misses *コストで、メインストリームは最初のダウンを、Azulを2番目にダウンさせようとします。)AzulのJava Compute Acceleratorsは、20000の同時キャッシュミスが発生していても、進行する可能性があります。
Azulが開始したとき、彼らはthought既成のI/Oコンポーネントをいくつか取り、独自の専用CPUコアを設計しましたが、実際に何をしたのかneeding正反対でした。彼らはかなり標準的な既製の3アドレスRISCコアを採用し、独自のメモリコントローラー、MMU、およびキャッシュサブシステムを設計しました。
tl; dr:Pythonの「遅さ」は言語のプロパティではありませんが、a)単純な(プライマリ)実装です、およびb)最近のCPUとOSはCを高速に実行するように特別に設計されており、Cに備わっている機能が(キャッシュ)を支援していないか、または(仮想メモリ)Pythonのパフォーマンスを積極的に阻害している。
そして、動的アドホック多態性を備えたほぼすべてのメモリ管理言語をここに挿入できます。効率的な実装の課題に関しては、PythonとJavaもかなりです "同じ言語」。
Pythonの現在の実装(他の動的言語によって実行される多くの最適化が欠如している、たとえば最新のJavascript実装や、ご指摘のとおり、Lua)はそのほとんどの問題の原因ですが、それを引き起こすいくつかの意味上の問題があります少なくとも特定の分野では、実装が他の言語と競合することは困難です。特に検討する価値のあるもの:
リストおよびディクショナリ操作は、言語定義がアトミックであるために必要です。これは、JITコンパイラがリストオブジェクトへの参照が現在のスレッドをエスケープしていないことを証明できない場合(多くの場合は困難であり、一般的なケースでは不可能である分析)は、オブジェクトへのアクセスが確実にシリアル化される必要があることを意味します(たとえばロックを介して)。 CPython実装は、悪名高い「グローバルインタープリターロック」を使用してこの問題を解決します。これにより、マルチスレッド技術を使用するマルチプロセッシング環境でPythonコードが効果的に使用されなくなり、他のソリューションも可能ですが、すべてパフォーマンスがあります。問題。
Pythonには、値オブジェクトの使用を指定するメカニズムはありません。すべてが参照によって処理され、必ずしも必要ではない場合に、間接参照が追加されます。 JITコンパイラが値オブジェクトを推測して自動的に最適化することは可能ですが、一般的には不可能であるため、最適化が確実に行われるように慎重に記述されていないコード(これはやや黒字です)です。苦しむでしょう。
Pythonにはeval
関数があります。つまり、JITコンパイラーは、プログラム全体の分析を実行しても、eval
が1回使用されている限り、アクションが発生しないことを想定できません。たとえば、Pythonコンパイラは、クラスにサブクラスがないと想定できないため、メソッド呼び出しを非仮想化します。これは、後でeval
を呼び出してその想定を否定できるためです。代わりに、動的型チェックを実行して、ネイティブコンパイルコードによって行われた仮定がそのコードの実行前に無効化されていないことを確認します。