見撮影ジュリアのウェブページを、あなたは、いくつかのアルゴリズム(タイミングは、以下に示す)間でいくつかの言語のいくつかのベンチマークを見ることができます。もともとCで書かれたコンパイラーを備えた言語は、Cコードよりも優れているのでしょうか?
見撮影ジュリアのウェブページを、あなたは、いくつかのアルゴリズム(タイミングは、以下に示す)間でいくつかの言語のいくつかのベンチマークを見ることができます。もともとCで書かれたコンパイラーを備えた言語は、Cコードよりも優れているのでしょうか?
回答:
コンパイラーの実装とコンパイラーの出力との間に必要な関係はありません。最も一般的な実装が非常に遅いPythonやRubyのような言語でコンパイラを書くことができ、そのコンパイラはCよりも優れた高度に最適化されたマシンコードを出力できます。コンパイラ自体は実行に時間がかかります。コードは遅い言語で書かれています。(より正確に言うと、実装が遅い言語で書かれています。言語は、Raphaelがコメントで指摘しているように、本質的に高速でも低速でもありません。以下でこの考えを拡張します。)独自の実装が許可されています。Fortranコンパイラと同じマシンコードを生成するコンパイラをPythonで作成でき、コンパイルに時間がかかりますが、コンパイルされたプログラムはFortranと同じくらい高速です。
通訳について話している場合は、別の話です。通訳者は、解釈するプログラムの実行中に実行する必要があるため、インタープリターが実装されている言語と、解釈されたコードのパフォーマンスとの間には関係があります。インタープリターが実装されている言語よりも高速に実行されるインタープリター言語を作成するには、いくつかの巧妙なランタイム最適化が必要です。JavaやC#などの多くの言語は、インタープリターの利点の一部とコンパイラの利点の一部を組み合わせたハイブリッドモデルでランタイムを使用します。
具体的な例として、Pythonをより詳しく見てみましょう。Pythonにはいくつかの実装があります。最も一般的なのは、CPythonで、Cで記述されたバイトコードインタープリターです。PyPyもあります。これは、RPythonと呼ばれるPythonの特殊な方言で記述され、JVMに似たハイブリッドコンパイルモデルを使用します。PyPyは、ほとんどのベンチマークでCPythonよりもはるかに高速です。あらゆる種類の驚くべきトリックを使用して、実行時にコードを最適化します。ただし、PyPyが実行するPython言語は、CPythonが実行するPython言語とまったく同じであり、パフォーマンスに影響しないいくつかの違いはありません。
Fortran用のPython言語でコンパイラを作成したとします。コンパイラはGFortranと同じマシンコードを生成します。次に、Fortranプログラムをコンパイルします。CPythonの上でコンパイラを実行することも、PyPyで実行することもできます。これは、Pythonで書かれており、これらの実装の両方が同じPython言語を実行するためです。コンパイラをCPythonで実行し、PyPyで実行し、GFortranで同じFortranソースをコンパイルすると、まったく同じマシンコードが3回すべて取得されるため、コンパイルされたプログラムは常に実行されますほぼ同じ速度で。ただし、コンパイルされたプログラムの作成にかかる時間は異なります。CPythonはPyPyよりも時間がかかる可能性が高く、PyPyはGFortranよりも時間がかかる可能性が高くなりますが、それらのすべてが最後に同じマシンコードを出力します。
Julia Webサイトのベンチマークテーブルをスキャンすると、インタープリターで実行されている言語(Python、R、Matlab / Octave、Javascript)のどれもCに勝るベンチマークを持たないように見えます。 Pythonの高度に最適化されたNumpyライブラリ(CおよびFortranで記述された)で記述されたコードが、同様のコードのC実装の可能性を破ることを想像できましたが。C以上の言語がコンパイルされている(Fortran、Julia)か、部分的なコンパイルでハイブリッドモデルを使用している(Java、およびおそらくLuaJIT)。PyPyもハイブリッドモデルを使用しているため、CPythonではなくPyPyで同じPythonコードを実行した場合、実際にはいくつかのベンチマークでCに勝る可能性があります。
男が作った機械は、どうして男よりも強くなるのでしょうか?これはまったく同じ質問です。
答えは、コンパイラの出力は、コンパイラの実装に使用される言語ではなく、そのコンパイラによって実装されるアルゴリズムに依存するということです。非常に効率的なコードを生成する、非常に低速で非効率的なコンパイラを作成できます。コンパイラについて特別なことは何もありません。それは、入力を受け取り、出力を生成する単なるプログラムです。
私は、私の意見では、仕事のためのツールを選択する際に有害であるという点に誤解しているという一般的な仮定に対して1つのポイントを作りたいと思います。
遅いまたは速い言語のようなものはありません。¹
CPUが実際に何かをしている途中で、多くのステップがあります²。
個々のアイテムはすべて、測定できる実際のランタイムに貢献しますが、場合によっては大きくなります。さまざまな「言語」は、さまざまなことに焦点を当てています³。
例を挙げます。
1対2-4:平均的なCプログラマーは、正確さと効率の両方の点で、平均的なJavaプログラマーよりもはるかに悪いコードを生成する可能性があります。これは、プログラマがCでより多くの責任を負うためです。
1/4 vs 7:Cのような低レベル言語では、プログラマーとして特定のCPU機能を活用できる場合があります。高水準言語では、コンパイラー/インタープリターのみがこれを行うことができ、ターゲットCPU を知っている場合のみです。
1/4 vs 5:メモリアーキテクチャを最大限に活用するために、メモリレイアウトを制御する必要がありますか?一部の言語ではそれを制御できますが、そうでない言語もあります。
2/4 vs 3:解釈されたPython自体はひどく遅いですが、高度に最適化された、ネイティブにコンパイルされた科学計算用ライブラリへの一般的なバインディングがあります。そのため、Pythonで特定の処理を行うことは、ほとんどの作業がこれらのライブラリによって行われる場合、最終的には高速になります。
2 vs 4:標準のRubyインタープリターは非常に遅いです。一方、JRubyは非常に高速です。別のコンパイラ/インタプリタを使用すると、同じ言語が高速になります。
1/2 vs 4:コンパイラーの最適化を使用すると、単純なコードを非常に効率的なマシンコードに変換できます。
一番下の行は、あなたが見つけたベンチマークはあまり意味をなさない、少なくともあなたが含むそのテーブルに要約されたときはそうではありません。実行時間だけに関心がある場合でも、プログラマからCPUまでのチェーン全体を指定する必要があります。いずれかの要素を交換すると、結果が劇的に変わる可能性があります。
コンパイラー(ステップ4)が記述されている言語はパズルの一部にすぎず、おそらくまったく関連していないことを示しているため、これは質問に答えています(他の回答を参照)。
ここでは意図的に異なる成功指標には触れません:実行時間効率、メモリ効率、開発者時間、セキュリティ、安全性、(証明可能?)正確性、ツールサポート、プラットフォームの独立性、...
完全に異なる目標のために設計されているにもかかわらず、1つのメトリックと言語を比較することは、大きな誤りです。
ここで最適化について忘れられていることが1つあります。
フォートランがCをアウトパフォームすることについては長らく議論がありました。不正なディベートを区別する:同じコードがCとフォートランで記述され(テスターが考えたように)、パフォーマンスは同じデータに基づいてテストされました。問題は、これらの言語は異なりますが、Cではポインターのエイリアスを許可しますが、Fortranでは許可しません。
したがって、コードは同じではなく、Cテスト済みファイルには__restrictがありませんでした。これは、コンパイラーにポインターを最適化できることを伝えるためにファイルを書き換えた後、ランタイムが似たものになるCテストファイルにありません。
ここでのポイントは、いくつかの最適化手法が、新しく作成された言語でより簡単である(または合法になり始める)ということです。
また、それはJITのより性能が優れCとVMに長期的には可能である2つの可能性があります:
JITコードは、それが(例えば、いくつかのSSE、それをホストしているマシンを利用することができますまたは一部のCPUが命令をベクトル化するために、他の排他的)に実装されていませんでした比較プログラム。
第二に、VMは実行中に圧力テストを実行できるため、圧力のかかったコードを取得して最適化したり、実行時に事前計算したりすることさえできます。事前にコンパイルされたCプログラムは、圧力がどこにあるか、または(ほとんどの場合)一般的なマシンファミリの実行可能ファイルの汎用バージョンがあることを予期していません。
このテストにはJSもあり、V8よりも高速なVMがあり、一部のテストではCよりも高速に実行されます。
私はそれをチェックしましたが、Cコンパイラではまだ利用できない独自の最適化手法がありました。
Cコンパイラーは、コード全体の静的分析を一度に行い、特定のプラットフォーム上を行進し、メモリーアライメントの問題を回避する必要があります。
VMは、コードの一部を最適化されたアセンブリに変換して実行しました。
ジュリアについて-チェックしたように、コードのASTで動作します。たとえば、GCCはこのステップをスキップし、最近そこから情報を取得し始めました。これに加えて、他の制約とVMテクニックが少し説明されるかもしれません。
例:単純なループを使用して、変数から開始終了点を取得し、実行時に既知の計算に変数の一部をロードします。
Cコンパイラは、レジスタからロード変数を生成します。
ただし、実行時にはこれらの変数は既知であり、実行を通じて定数として扱われます。
したがって、レジスターから変数をロードする代わりに(そして、変更される可能性があるためキャッシングを実行せず、静的解析からは明確ではありません)、変数は定数のように完全に扱われ、伝播されます。
ラファエルの答えでうまく説明されているように、これまでの答えはほとんど説明を提供しますが、ほとんどは実用的な角度からです。
この答えに加えて、今日では、CコンパイラはCで書かれていることに注意する必要があります。もちろん、Raphaelが指摘したように、その出力とパフォーマンスは、実行中のCPUに依存します。しかし、それはコンパイラーによって行われた最適化の量にも依存します。CでCの最適化コンパイラーを作成すると(古いコンパイラーでコンパイルして実行できるようになります)、Cを以前よりも高速な言語にする新しいコンパイラーが得られます。それでは、Cの速度はどのくらいですか? 2番目のパスとして、新しいコンパイラ自体をコンパイルすることもできます。これにより、同じオブジェクトコードを提供しながら、より効率的にコンパイルできます。そして、完全な雇用定理は、彼らがそのような改善に終わりがないことを示しています(ポインタについてラファエルに感謝します)。
しかし、いくつかの基本的な概念、特に物事の表示と操作の観点を非常によく示しているので、問題を形式化することは価値があると思います。
コンパイラと略記、、全くあいまいさがない場合には、計算機能の実現であるプログラムテキストを翻訳する演算機能に書き込まれ、ソース言語プログラムテキストにに書き込まれた ターゲット言語、それは、同じ関数を計算することになっている。
セマンティックの観点から、つまり表示的には、このコンパイル関数がどのように計算されるか、つまりどの実現が選択されるかは問題ではありません。それは魔法の神託によってさえ行われる可能性があります。数学的には、関数はペアのセットです。
と両方が同じ関数計算する場合、セマンティックコンパイル関数は正しいです。しかし、この形式化は正しくないコンパイラにも適用されます。唯一のポイントは、実装されたものが何であれ、実装手段に関係なく同じ結果が得られることです。意味的に重要なのは、コンパイラーによって行われることであり、その方法(および速度)ではありません。
実際、から取得することは運用上の問題であり、解決する必要があります。これが、コンパイル関数が計算可能な関数でなければならない理由です。チューリングの能力を備えた言語であれば、どれほど遅くても、たとえ他の言語ほど効率的でなくても、他の言語と同じくらい効率的にコードを生成できます。
引数を精緻化するために、おそらくコンパイラーの効率を良くして、翻訳を妥当な時間で実行できるようにする必要があります。したがって、ユーザーにとってコンパイラプログラムのパフォーマンスは重要ですが、セマンティクスには影響しません。一部のコンパイラの理論的な複雑さは、予想よりもはるかに高くなる可能性があるため、パフォーマンスと言っています。
これは区別を説明し、実用的なアプリケーションを示します。
現在、最初にインタプリタで言語を実装し、次に言語自体でコンパイラを記述するのが一般的な場所です。このコンパイラーは、インタープリター実行して、プログラムをプログラムに変換できます。したがって、言語から(マシン?)言語までのコンパイラーが実行されていますが、インタープリター上で実行されるためだけに非常に遅いです。I S C S → T S C S → T I S P :S P :T ST
ただし、このコンパイル機能を使用してコンパイラをコンパイルできます。これ は言語で記述されているため、コンパイラがターゲット言語。多くの場合、がより効率的に解釈される言語(たとえば、マシンネイティブ)であると仮定すると、言語直接実行されるコンパイラの高速バージョンが得られます。まったく同じジョブを実行します(つまり、同じターゲットプログラムを生成します)が、より効率的に実行します。 S C S → T TTT
Blumの高速化定理により、インタプリタBASICを実行している最初のPC上の同じプログラムよりも実行速度が非常に速いコンピュータ/コンパイラの組み合わせで実行されるプログラムがあります。「最速の言語」はありません。言えることは、同じアルゴリズムを複数の言語で記述した場合(実装;前述のように、さまざまなCコンパイラが多数存在し、かなり有能なCインタープリターに出くわしたこともあります)、それぞれで高速または低速で実行されることです。
「常に遅い」階層は存在できません。これは、いくつかの言語に堪能な人なら誰でも知っている現象です。各プログラミング言語は特定の種類のアプリケーション用に設計されており、使用される実装はその種類のプログラム用に最適化されています。例えば、Perlで書かれた文字列をだまし取るプログラムは、おそらくCで書かれた同じアルゴリズムに勝ると思いますが、Cの整数の大きな配列をむしゃむしゃするプログラムはPerlより高速です。
元の行に戻りましょう:「コンパイラがCで記述されている言語は、Cよりも高速になりますか?」 これは本当に言ったつもりだったと思う:コアがCで書かれているJuliaで書かれたプログラムは、Cで書かれたプログラムよりも速くなることができるのか?具体的には、ジュリアで書かれた「マンデル」プログラムは、Cで書かれた同等の「マンデル」プログラムの実行時間の87%でどのように実行できますか?
これまでのところ、バブーの論文はこの質問に対する唯一の正しい答えです。これまでの他のすべての回答は、多かれ少なかれ他の質問に答えています。babouのテキストの問題は、「パラグラフとは何か」の多くの段落にわたる理論的記述が、元のポスターがおそらく理解するのに苦労するという用語で書かれていることです。「セマンティック」、「表示」、「実現」、「計算可能」などの言葉で言及されている概念を理解している人は誰でも、すでに質問に対する答えを知っているでしょう。
より簡単な答えは、CコードもJuliaコードもマシンで直接実行できないことです。両方とも翻訳する必要があり、その翻訳プロセスにより、実行可能なマシンコードが遅くなったり速くなったりする可能性がありますが、それでも同じ最終結果が生成されます。Cとジュリアはどちらもコンパイルを行います。つまり、別の形式への一連の翻訳を意味します。一般に、人間が読めるテキストファイルは内部表現に変換され、コンピューターが直接理解できる一連の命令として書き出されます。一部の言語では、それだけではありません。Juliaもその1つです。「JIT」コンパイラーを備えているため、プログラム全体で翻訳プロセス全体を一度に行う必要はありません。しかし、すべての言語の最終結果は、それ以上の翻訳を必要としないマシンコードです。CPUに直接送信して何かをさせることができるコード。結局、これは「計算」であり、CPUに必要な答えを得る方法を伝える方法は複数あります。
「プラス」演算子と「乗算」演算子の両方を持つプログラミング言語と、「プラス」のみを持つ別の言語を想像できます。計算に乗算が必要な場合、もちろんCPUは両方を直接実行できるため、1つの言語は「遅くなります」が、5 * 5を乗算する必要性を表現する方法がない場合は、「5 + 5 + 5 + 5 + 5 "。後者は同じ答えに到達するのにより多くの時間がかかります。おそらく、Juliaでこれが進行中です。おそらくこの言語により、プログラマーはCで直接表現できない方法でマンデルブロ集合を計算するという目標を述べることができます。
ベンチマークに使用されたプロセッサは、Xeon E7-8850 2.00GHz CPUとしてリストされました。Cベンチマークはgcc 4.8.2コンパイラを使用してそのCPUの命令を生成しましたが、ジュリアはLLVMコンパイラフレームワークを使用しました。gccのバックエンド(特定のCPUアーキテクチャ用のマシンコードを生成する部分)が、LLVMバックエンドほど高度ではない可能性があります。これにより、パフォーマンスに違いが生じる可能性があります。他にも多くのことが行われています-コンパイラーは、おそらくプログラマーによって指定された順序とは異なる順序で命令を発行することで「最適化」できます。コードを分析し、そうでないと判断できる場合は、何もしない正しい答えを得るために必要です。そして、プログラマーはCプログラムの一部を遅くする方法で書いたかもしれませんが、
これらはすべて言い方です。マンデルブロ集合を計算するマシンコードを記述する方法は数多くあり、使用する言語はそのマシンコードの記述方法に大きな影響を与えます。コンパイル、命令セット、キャッシュなどについて理解すればするほど、必要な結果を得るための準備が整います。ジュリアのために引用されたベンチマーク結果からの重要なポイントは、すべての点で最適な言語やツールはないということです。実際、チャート全体で最高の速度係数はJavaでした!
コンパイラがCで記述された言語Xで記述されたコードは、Cで記述されたコードよりも優れている場合があります。ただし、Cコンパイラは言語Xに比べて最適化が不十分です。 Cコンパイラーによって生成されたものよりもオブジェクトコード、そしてXで記述されたコードも競合に勝つ可能性があります。
しかし、言語Xがインタープリター言語であり、インタープリターがCで書かれており、言語XのインタープリターとCで書かれたコードが同じCコンパイラーでコンパイルされていると仮定した場合、Xで書かれたコードはコードを上回ることはありません両方の実装が同じアルゴリズムに従い、同等のデータ構造を使用する場合、Cで記述されます。