実行時コンパイラはどうやって高速処理を実現しているのか? #2
現在公開中のポッドキャスト「実行時コンパイラはどうやって高速処理を実現しているのか?」をテキストでご紹介します。
出演:石井敦(クーガーCEO) / 土田悠貴(クーガー ヒューマンエージェントアーキテクト) 今回は全2エピソードの第2回目です。

石井:まったく同じ行動が2回目に実行される時はどうなるのでしょうか?
土田:また収集し直しです。
石井:インタプリタ画面ですね?それでもC++ネイティブなみのスピードを出せるということですね?
土田:はい、JITの部分が優秀なのか、スピードは出せます。
石井:一度実行したキャッシュのようなものを敢えて置かない訳ですね?
土田:まだ置けないのかもしれませんね。少なくともブラウザなどのAPIだと置けるものではないですね。V8エンジンのソースを直接たたいて繰り出す方法がある可能性はあります。V8エンジンを直接使っていると、JITがかからないけれど、食わせる部分というのがあるんですね。結局バイナリのデータなので、途中で差し込めるインターフェイスを作ってあげれば良いという話だと思います。
石井:分かってきました。JITでJust In Timeでやることに集中している方が、中途半端に前の実行のキャッシュのバイナリがどうだとやるより早いということなんでしょうね。柔軟性を持たせた状態でスピードを出すというような。
土田:はい、そう思います。あと、前の結果って何なのか、例えば一文字でも違ったら別のコードですよね。チェックサムをとっても同じ値にはならないので。何をもって前と同じと見るかという保証が難しいと思うんですよ。結局ストレージやメモリの圧迫になってしまう。
石井:なるほど、確かに。持っておいたものをまた読まなければいけないから。
土田:そうです。それを結局メモリに展開するので。

石井:リソースもメモリも限りがあるし、Just In Timeだとメモリ側の処理が重要なんですよね。リアルタイムのC++なみのかなりのスピードを出してはいますが、何か課題はありますか?もしくはもっとこうなればより良いといったような。
土田:統計情報を取っているので仕方がないところはあると思うのですが、どのタイミングで最適化がかかるのかが、いまいちわからないというのが問題でしょうか。C++は出力されたコードのバイナリを見ればわかるのですが、JavaScriptでJITがかかって最適化されたけれど、人のブラウザ環境でどうなっているのかはわからない。そこは任せてしまっているので見られなくてもいいという考え方もあると思うのですが、どのタイミングで最適化がかかるかわからないので、こんな風にかかるはずだからこう書いた方が効率がいい、こういうイメージだからこうしている、ということです。
石井:なるほど、それは結構AIに近いですね。機械学習やディープラーニングと言われているものは、Explainable AI、説明できるAIは、統計が入れば入るほど、なぜこの結果になるのかが分からなくなってくるんですよ。AIに学習させて精度は上がった、おおよそこれらの学習をさせたということはわかっても、完璧には難しい。土田さんがおっしゃったことはそれに近いですよね。JITコンパイラの中のアルゴリズム自体に統計のかなり複雑な処理が入っていて、それがまさに機械学習が統計して出すのと同じことをやっているのではないでしょうか。
土田:確かにそうですね。統計を取ってという部分で考えると、同じことをやってそうです。
石井:そうすると、例えば最適化している状態と、実際出たもの、こういう処理だとこういう結果になったというような因果関係を、これ自体を学習させていけばすごいJITコンパイラができるんじゃないですか?要は最適化の部分をさらに自動学習するようなことです。
土田:確かに。
石井:おそらく統計も実行処理から考えて何らかの法則で一番効率的なものを選んでいると思うのですが、それは例えば自動運転と人型AIとドローンで使う場合では最適化すべきものが変わると思うんですよね。最適化する統計のパラメータが自動的に変わるようになったらすごいですよね。バーチャルヒューマンの場合は、この部分が最適化されるといったような。
土田:そこまでやってくれると確かにすごいですね。物によって操作も違うので、そこを考慮してやってくれるといいですね。
石井:人間である意味でそれをしているんです。自分の過去の経験を活かして自分の判断ができるんですよね。

石井:では課題としては、統計の部分がブラックボックスであって、JITコンパイラの場合は、統計を使っている分、あるパフォーマンスが出たり出なかったりといった、わからない部分がある。例えばJITコンパイラの仕様を知り尽くした人が逆にそれを利用して超速スピードのプログラムを書くといったこともあり得ますよね。
土田:そうですね、癖を知っていればプログラムをこう書けばこういう結果になるのは見えるので、V8エンジンのJITの場合は、最初はAを通っていたのに次に起動するとAを通らないような、操作によって変わるんですね。それによって実行時に処理速度を最適化する部分に関して言うと、Aは今回使わないのでここは最適化しなくてよい、でも次回使うから最適化はその時にする、という差が出てくる。性質をよく知っていると、重いコードは頻繁に通るこの辺りに置いていこう、といったことが出来ると思います。
石井:本来は通さないといけないところをうまく通してドーピングのようなことをする感じですかね。
土田:確かにできそうですね(笑)。
石井:ゲームユーザーがすごいと思うところは、昔のゲームでこれ以上通れるルートはないとか、信じられないルートを通ったりする人がいますが、それに近いと思うんですよね。制限が決まっているからこそ、追及しまくるというケースですね。
土田:ゲームは確かにそういう楽しみがありますね。例えばメタルギアソリッドのシリーズで、動画で敵の動きを良くわかっている人は、敵の目の前で動いているのに見つからないことがあるんですよね。普通は見つかるだろうと思うんですが、なぜか見つからず動けるプレイヤーがいて、すごく驚きました。
石井:当たり判定みたいな処理を見越してちょっとずれるんでしょうね。
土田:タイミングもですよね。メタルギアソリッドの主人公スネークを見つけたらビックリマークが出るんですが、マークが出た瞬間はまだ敵は警戒モードに入っていないのか、その瞬間に捕まえることができるジャストなタイミングを極めまくるみたいな。
石井:なるほど。実行時コンパイラならではですが、使い方の逆アセンブルみたいなことですね。そういったことがわかるとより強力なJITコンパイラを作るきっかけになったり、それによって新たな技術が生まれたりするかもしれませんね。本日はJITコンパイラについて深い話をしてきました。まだ話は尽きないですが、また次回新しいトピックで話そうと思います。土田さん、今日はありがとうございました。
土田:ありがとうございました。

クーガーは自律的で大胆なチャレンジを支援し、それぞれの個性を生かした技術と創造性の追求ができる場を目指しています。
ぜひ採用ページからエントリーください。カジュアル面談も実施しています!
最新情報をメールで取得
登録
© Couger Inc. All rights reserved.