4

OK、最初に、私はここでどんな種類の炎上戦争もそれのようなものを望んでいません。私のより大きな質問はより理論的であり、いくつかの例が含まれます。

ですから、私が書いたように、通訳言語がどのように少しでも効率的であるのか理解できません。そして、その現代以来、私は例としてJavaを取り上げます。

JITコンパイラがなかった時代に戻りましょう。Javaには、基本的にハードウェアである仮想マシンがあります。仮想マシンから少なくとも一部のジョブを削除するためにバイトコードにコンパイルされるよりも、コードを記述します。それで問題ありません。しかし、RISC命令セットでさえハードウェアでどれほど複雑になる可能性があるかを考えると、ソフトウェアでエミュレートされたハードウェアでそれを行う方法を考えることすらできません。

私は仮想マシンを作成した経験がないので、それが最も効率的なレベルでどのように行われるかはわかりませんが、適切なアクションを実行するよりも、一致と一致についてすべての命令をテストするよりも効率的なことは考えられません。あなたが知っている、のようなもの:if(instruction=="something") { (do it) } else if(instruction=="something_diffrent"){ (do it) }など...

しかし、これはひどく遅くなければなりません。それでも、JavaがJITコンパイラの前に遅いという記事があったとしても、それほど遅くはないと言われています。ただし、エミュレートするには、1バイトコード命令を実行するために実際のHWの多くのクロックサイクルが必要です。

それでも、プラットフォーム全体でさえJavaに基づいています。たとえば、Android。そして、Androidの最初のバージョンにはJITコンパイラがありませんでした。それらは解釈されました。しかし、Androidをひどく遅くするべきではありませんか?それでもそうではありません。AndroidライブラリからAPI関数を呼び出すと、それらはマシンコードで記述されているため、効率的であるため、非常に役立ちます。

ただし、画像を表示するためだけにAPIを使用して、独自のゲームエンジンを最初から作成することを想像してみてください。多くの配列コピー操作を実行する必要があります。多くの計算は、エミュレートすると非常に遅くなります。

そして今、私が約束したいくつかの例。私は主にMCUを使用しているので、AtmelAVRMCU用のJVMを見つけました。Thayは、8MHZMCUが1秒あたり20KのJavaオプトコードを実行できると述べています。しかし、AVRは1または2サイクルでほとんどの命令を実行できるので、平均して6000000命令としましょう。これにより、JITコンパイラを使用しないJVMは、マシンコードの処理速度が300倍遅くなります。では、なぜJITコンパイラなしでJavaがそれほど人気になるのでしょうか。これはパフォーマンスの低下がひどいのではないですか?理解できません。ありがとう。

4

4 に答える 4

3

私たちは長い間バイトコードを持っていました。古いAppleIIでは、USCD pシステムが非常に人気があり、Pascalをバイトコードにコンパイルしました。これは、2MHzで実行されている可能性のある8ビット6502によって解釈されます。それらのプログラムはかなり速く実行されました。

if/then/elseバイトコードインタープリターは、通常、ステートメントのチェーンではなく、ジャンプテーブルに基づいています。CまたはC++では、これにはswitchステートメントが含まれます。基本的に、インタプリタは処理コードの配列に相当し、バイトコード命令のオペコードを配列のインデックスとして使用します。

マシン命令よりも高レベルのバイトコードを使用することも可能です。これにより、1バイトコード命令が複数の、場合によっては多数のマシンコード命令に変換されます。特定の言語用に構築されたバイトコードは、その特定の言語の制御およびデータ構造と一致する必要があるだけなので、これをかなり簡単に行うことができます。これにより、解釈のオーバーヘッドが拡大し、インタプリタがより効率的になります。

インタプリタ言語は、コンパイル言語と比較した場合、速度が低下する可能性がありますが、これは多くの場合重要ではありません。多くのプログラムは人間の速度で入力と出力を処理します、そしてそれは無駄にされることができる途方もない量のパフォーマンスを残します。ネットワークにバインドされたプログラムでさえ、必要以上のCPUパワーを利用できる可能性があります。取得できるすべてのCPU効率を使用できるプログラムがあり、明らかな理由から、インタープリター言語で記述されていない傾向があります。

そしてもちろん、違いを生むかもしれないし、生まないかもしれないいくつかの非効率性のためにあなたが何を得るかという問題があります。インタプリタされた言語の実装は、コンパイルされた実装よりも移植が容易である傾向があり、実際のバイトコードは移植可能であることがよくあります。言語に高レベルの機能を追加する方が簡単な場合があります。これにより、コンパイルステップを大幅に短縮できます。つまり、実行をはるかに高速に開始できます。何か問題が発生した場合に、より適切な診断が可能になる場合があります。

于 2010-09-02T20:35:44.350 に答える
0

この質問に取り組むには2つの異なる方法があります。

(i)「スローコードを実行してもよいのはなぜですか」

ジェームズがすでに上で述べたように、実行速度だけが興味のあるものではない場合があります。解釈モードで実行されている多くのアプリでは、「十分に高速」である可能性があります。作成しているコードがどのように使用されるかを考慮する必要があります。

(ii)「なぜコードが不十分であると解釈されるのか」

インタプリタを実装する方法はたくさんあります。あなたの質問では、最もナイーブなアプローチについて話します。基本的には大きなスイッチであり、読み取られた各JVM命令を解釈します。

ただし、これを最適化することはできます。たとえば、単一のJVM命令を調べる代わりに、それらのシーケンスを調べて、より効率的な解釈が可能なパターンを探すことができます。SunのJVMは、実際には、インタープリター自体でこれらの最適化の一部を実行します。以前の仕事では、ある人がインタプリタをそのように最適化するのに少し時間がかかり、解釈されたJavaバイトコードは彼の変更後に著しく速く実行されていました。

しかし、JITコンパイラーを含む最新のJVMでは、インタープリターはJITがその仕事をするまでの足がかりにすぎないため、インタープリターの最適化にそれほど多くの時間を費やすことはありません。

于 2010-09-02T20:34:18.987 に答える
0

しかし、Androidをひどく遅くするべきではありませんか?

「ひどく遅い」を定義します。それは電話です。2桁目をダイヤルする前に、「1桁目をダイヤル」を処理する必要があります。

インタラクティブなアプリケーションでは、制限要因は常に人間の反応時間です。ユーザーよりも100倍遅くても、高速である可能性があります。

ですから、あなたの質問に答えるために、はい、通訳は遅いですが、特にハードウェアが速くなり続けるので、彼らは通常十分に速いです。

Javaが導入されたとき、それはWebアプレット言語として販売されていたことを思い出してください(Javascriptに置き換えられ、現在はJavascriptに置き換えられています---これも解釈されます)。それがサーバーで普及したのは、JITコンパイルの後でのみでした。

バイトコードインタープリターは、ジャンプテーブルを使用することにより、if()の行よりも高速になります。

 void (*jmp_tbl)[256] = ...;  /* array of function pointers */
 byte op = *program_counter++;
 jmp_tbl[op]();
于 2010-09-02T20:26:50.940 に答える
0

12 MHzは、8ビットマイクロプロセッサであるATtinyになります。つまり、(たとえば)ネイティブの「Add」命令は2つの8ビット数値を足し合わせて9ビットの結果を得ることができます。JVMは基本的に仮想32ビットプロセッサです。つまり、そのadd命令は2つの32ビットを追加します。ビット番号を合わせて33ビットの結果を生成します。

そのため、命令レートを比較する場合、絶対最小値として命令レートが4:1減少することを期待する必要があります。実際には、32ビットの加算と4つの8ビットの加算(キャリー付き)をシミュレートするのは簡単ですが、そのようにスケーリングされないものもあります。たとえば、Atmel自身のアプリノートによると、32ビットの結果を生成する16x16の乗算は、約218クロックサイクルで実行されます。同じアプリノートは、255サイクルで実行される16/16ビット除算(8ビット結果を生成)を示しています。

これらのスケールが線形であると仮定すると、32ビットバージョンの乗算には約425〜450クロックサイクル、除算には約510サイクルかかると予想できます。実際には、多少のオーバーヘッドが予想されますが、これにより速度がさらに低下します。これらの見積もりに少なくとも10%を追加すると、おそらくより現実的になります。

結論:リンゴとリンゴを比較すると、話している速度の違いの多くがまったく現実的ではないことが明らかになります(または、とにかくJVMのオーバーヘッドに起因するものではありません)。

于 2010-09-02T20:52:26.677 に答える