* Essen Rev2 (ess03h) -(by [[K]], 2017.08.23) ** これはなに? -[[EssenR2_ess03f]]の改良版です。 ** 主な差分 -大半の項目はすごいことではなく、むしろ今まできちんと作っていなかったことが問題だったというだけ。 -[1]グラフィックス描画ウィンドウを途中で閉じても例外が出なくなった(blaライブラリの改良)。 -[2] ! ~ - + などの単項演算子が機能するようになった。 -[3] & | ^ などの二項演算子が機能するようになった。 -[4] a = b < c みたいな演算が可能になった。 -[5] 最適化機能の強化。 -[6] $i00~$i03が利用可能になった。 ** 例1: シンプルな20億回ループ(1) -まずは、シンプルな20億回ループを書いてみる。 i = 0 while (i < 2000000000) { i++ } -ess03hにはまだfor構文がないので、素直に20億回ループを書くとこうなる。 -これを prompt>ess03h sample1.txt na で処理させると、JITコンパイルで生成したx86のアセンブラコードが出てくる。 MOV $EAX c##s20#00000000$ MOV g032 $EAX label L000000001 MOV $EAX g032 ADD $EAX c##s20#00000001$ MOV g032 $EAX CMP $EAX c##s20#77359400$ JL L000000001 -まあたいしたことないコードだ。当然たいして速くもない。なお、ADDで1を足している部分があるが、これをINCにしていないのはわざとである(ADDのほうがキャリーも含めて変化するので、フラグレジスタパーシャルレジスタストールの観点で好ましいケースがあるから)。 -これをCore_i7-2600/3.4GHz上で実行すると''4.24秒''くらいかかる。ちなみにソースコードをJITコンパイルして機械語に変換するまでに要した時間は0.001秒だった。 --JITコンパイル時間に関して言えば、50行程度のesmandelの場合は0.002秒である。 ** 例2: シンプルな20億回ループ(2) -ここで、変数iを整数専用レジスタに割り振ったらどうなるか。一行書くだけでよくて簡単なのでやってみよう。 i :== $i00 i = 0 while (i < 2000000000) { i++ } -これを同様にnaするとこうなる。 MOV $EBX c##s20#00000000$ label L000000001 ADD $EBX c##s20#00000001$ CMP $EBX c##s20#77359400$ JL L000000001 -EBXレジスタに割り当てられているのが見て取れる。無駄なメモリアクセス命令もなくなった。 -これをCore_i7-2600/3.4GHzで実行すると、''0.572秒''で終わってしまう。大幅に改善していることが分かる。簡単に7.4倍も速くなってしまった。 ** 例3: シンプルな20億回ループ(3) -もっと速くできないだろうか・・・実はできる。いくつかのCPUは0との比較であれば条件によっては省略することができる。x86もそれに該当する。ということで、カウントアップではなくカウントダウンにしてみる(まあマイナス20億からのカウントアップでもいいのだけれど)。 i :== $i00 i = 2000000000 while (i > 0) { i-- } -これをnaするとこうなる。 MOV $EBX c##s20#77359400$ label L000000001 SUB $EBX c##s20#00000001$ JG L000000001 -期待通りにCMP命令が無くなっているのが分かる。 -これをCore_i7-2600/3.4GHzで実行すると、''0.569秒''だった。・・・おや、これは誤差程度の改善しかしなかったようだ。きっとこのCPUではこの程度の改善には効果がないのだろう。 -先日AMDのCPUで試したときは効果があったのだが・・・。 -おそらくCore_i7-2600は優秀で、CMP命令があっても無いときと同じくらい高速に実行できていたのだろう。 ** 例4: シンプルな20億回ループ(4) -$i00の使用をやめた場合に、カウントダウン方式でどのくらい速いのか確認してみた。 i = 2000000000 while (i > 0) { i-- } -これをnaするとこうなる。 MOV $EAX c##s20#77359400$ MOV g032 $EAX label L000000001 MOV $EAX g032 SUB $EAX c##s20#00000001$ MOV g032 $EAX JG L000000001 -これをCore_i7-2600/3.4GHz上で実行すると3.91秒くらいかかる。例1と比べてこちらのほうが速いので、それなりに効果はあるようだ。 ** 議論: EssenRev2の最適化の方針について -最近のEssenRev2では、最適化をがんばっている。新しい命令の追加とかはほとんどやっていない。それはこう考えたからだ。 --(1) JITコンパイル方式での実行速度はあまりにも魅力的である。今までは「Essenは速度を追求しない、速度がほしければインラインC言語で書けばよい」という見解だったが、C言語との速度比があまりにも大きいと「もうめんどくさいから最初から全部C言語で書く」ということを検討してしまう。それは望ましくない。またC言語は機種依存(CPU依存)があるので、それも好ましくない。 --(2) となれば、なにはともあれJITコンパイラ部分を整備してしまうほうがいい。このレイヤは将来も使いまわせる。今後私がどんな言語を作ることになったとしても、流用できる。 --(3) JITコンパイル方式を採用したのは、JITコンパイラのエンジンがそれほど大きくならずに済むと分かったことも後押しになっている。 -Essenはgccとは最適化の方針が明らかに異なっている。その理由を説明したい。 // :==の後ろにコメントを入れられなかった。 -工事中 * こめんと欄 #comment