C、C ++などのJITコンパイラ


33

CやC ++などのコンパイル言語用のジャストインタイムコンパイラはありますか?(頭に浮かぶ最初の名前はClangとLLVMです!しかし、私は彼らが現在それをサポートしているとは思いません。)

説明:

このソフトウェアは、CやC ++などのコンパイルされたマシン言語でも、ランタイムプロファイリングフィードバックと、実行時のホットスポットの積極的に最適化された再コンパイルの恩恵を受けると思います。

プロファイルに基づく最適化も同様の仕事をしますが、異なる環境ではJITがより柔軟になります。PGOでは、リリースする前にバイナリを実行します。リリース後、実行時に収集された環境/入力フィードバックは使用されません。そのため、入力パターンが変更された場合、パフォーマンスの低下が発生します。しかし、JITはそのような状況でもうまく機能します。

ただし、JITコンパイルのパフォーマンス上の利点がそれ自体のオーバーヘッドを上回るかどうかについては議論の余地があると思います。


1
オフトピックのオフサイトリソース。
DeadMG

1
質問に合うかどうかはわかりませんが、使いやすさの観点から、Julia言語のCxxパッケージが便利だと思います。@PhilippClaßenの回答で説明されているような対話型のC ++プロンプトが表示されます。
アントネッロ

回答:


33

[現在、基本的に廃止されているまったく異なる回答については、編集履歴を参照してください。]

はい、Cおよび/またはC ++用のJITコンパイラがいくつかあります。

(ゲームから推測できるように)CLingはClang / LLVMに基づいています。通訳のように機能します。つまり、ソースコードを与え、実行するためのコマンドを与えると、実行されます。ここでの重点は、最大の最適化ではなく、主に利便性と高速コンパイルです。そのため、技術的には質問自体に対する回答ではありますが、これはOPの意図とはあまりよく一致しません。

別の可能性はNativeJITです。これは、質問とは多少異なります。特に、CまたはC ++のソースコードを受け入れず、コンパイルして実行します。むしろ、C ++プログラムにコンパイルできる小さなコンパイラです。基本的にC ++プログラム内でEDSLとして表現される式を受け入れ、そこから実際のマシンコードを生成し、それを実行できます。これは、ほとんどのプログラムを通常のコンパイラーでコンパイルできるフレームワークにはるかに適合しますが、実行時までわからないいくつかの式があり、最適な実行速度に近いもので実行したいです。

元の質問の明らかな意図については、元の答えの基本的なポイントがまだ残っていると思います:JITコンパイラは、実行ごとに異なるデータ、または単一の実行中に動的に変化するデータなどに適応できますが、現実には、これは少なくとも一般的なルールとしては、ほとんど違いがありません。ほとんどの場合、実行時にコンパイラを実行することは、かなりの最適化を控える必要があることを意味します。そのため、通常望んでいる最善策は、従来のコンパイラが生成する速度に近いことです。

JITコンパイラーで利用可能な情報により、従来のコンパイラーよりも大幅に優れたコードを生成できる状況を想定することは可能です、実際に発生するこのインスタンスは、非常に珍しいようです(そして、ほとんどの場合、検証できましたそれは、静的コンパイルモデルではなく、ソースコードの問題が原因でした)。


1
JITがキャッシュのようなファイルを保存して、すべてをゼロから再学習することをスキップできないのはなぜですか?
ジョンマッド

3
@JohnMudd:推論はセキュリティだと思う。たとえば、キャッシュされたコードを変更すると、次にVMが起動したときに、そこに書き込んだコードではなく、そこに置いたコードが実行されます。
ジェリーコフィン

4
OTOH、キャッシュを変更できる場合は、ソースファイルも変更できます。
user3125367

1
@ user3125367:はい。ただし、多くの場合、コンパイラはさまざまな型チェックを行います。コンパイルされたコードをキャッシュから直接ロードすると、コンパイラはバイパスされる可能性があります。もちろん、JITに依存します。Javaは(コンパイルされた).classファイルをロードするときに多くの実施作業を行いますが、他の多くはそれよりもはるかに少ない(多くの場合、ほとんどなし)。
ジェリーコフィン

11

はい、C ++用のJITコンパイラがあります。純粋なパフォーマンスの観点からは、プロファイルガイド型最適化(PGO)の方が優れていると思います。

ただし、それは、実際にJITコンパイルがまだ使用されていないことを意味するものではありません。たとえば、AppleはLLVMをOpenGLパイプラインのJITとして使用しています。これは、実行時にかなり多くの情報を保持するドメインであり、多くのデッドコードを削除するために使用できます。

JITのもう1つの興味深いアプリケーションは、LLVMおよびClangに基づく対話型C ++インタープリターであるClingです:https : //root.cern.ch/cling

サンプルセッションは次のとおりです。

[cling]$ #include <iostream>
[cling]$ std::cout << "Hallo, world!" << std::endl;
Hallo, world!
[cling]$ 3 + 5
(int const) 8
[cling]$ int x = 3; x++
(int) 3
(int const) 3
[cling]$ x
(int) 4

これはおもちゃのプロジェクトではありませんが、実際にはCERNで使用されており、たとえば、大型ハドロン衝突型加速器のコードを開発するために使用されています。


7

C ++ / CLIがあります。確かに、C ++ / CLIはC ++ではありませんが、かなり近いです。つまり、MicrosoftのJITは、少なくとも私の知る限りでは、ユーザーが求めているような、非常に巧妙でかわいい種類のランタイム動作ベースの最適化を行いません。したがって、これは本当に役に立ちません。

http://nestedvm.ibex.org/は、MIPSをJavaバイトコードに変換します。あなたの質問からこのアプローチの問題は、JITに到達するまでに多くの有用な情報を捨てることです。


2

まず、メソッドjitではなくトレースjitが必要だと思います。

最適なアプローチは、llvm IRにコードをコンパイルし、ネイティブ実行可能ファイルを生成する前にトレースコードを追加することです。コードブロックが十分に使用され、変数の(動的言語のような型ではない)に関する十分な情報が収集されると、変数の値に基づくガードを使用してコードを(IRから)再コンパイルできます。

libclangという名前でclangでac / c ++ jitを作成することで、いくつかの進歩があったことを覚えているようです。


1
私の知る限り、libclangはほとんどのclang機能がライブラリとして除外されています。そのため、ソースコードを分析して、洗練された構文の色付け、リント、コードブラウジングなどを作成するために使用できます。
Javier

@Javier、それは正しいと思う。ライブラリには、ソースコードのconst char *を使用してllvm irを生成する関数があったと思いますが、今は、ソースではなくirに基づいてjitする方がよいと考えています。
dan_waterworth
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.