• 検索結果がありません。

インタプリタの高速化における本研究の着眼点と新規性

第 2 章 C言語実装を用いたインタプリタ方式の命令エミュレータ性能

2.1. 命令エミュレーション技術

2.1.5. インタプリタの高速化における本研究の着眼点と新規性

本節では,本研究の着眼点を述べて新規性を示す.まず,概念レベルの着眼点について 述べる.

最近のエミュレータの研究ではバイナリ変換に関するものしか公表されておらず,イン タプリタ性能について定量評価する必要がある.しかしながら,インタプリタは古典的な 手法であり,その性能を評価した文献が見つからない.また,最近は高性能なRISCマイク ロプロセッサが普及しているため,処理性能を支配する条件が従来とは変わり新たな評価 が必要となると考える.

C言語記述のインタプリタ性能の予測は困難といわれているが,我々は予測の容易化は可 能であると考えている.それは,インタプリタには間接分岐が必要であり,また遂次性が

高いプログラム処理がコアループに多く存在すると考えるからである.最新のプロセッサ は高速化のために色々とハードウェアに工夫をしてきたが,遂次性が高いプログラム処理 の存在により,そのような工夫されたハードウェアが活かしにくくボトルネックになりや すい.そこで,コアループを定量評価すれば性能の目途が着くと考える.

また,C言語を用いてもコアループや実行頻度の高い命令をチューニングする手法は存在 すると我々は考える.バイナリ変換はインタプリタと比較して高速といわれその性能は断 片的に公表されており,そのバイナリ変換のスローダウン値からインタプリタのスローダ ウン値を逆算して求められる.そのインタプリタのスローダウン値が大きいことが,改善 の余地があると考えた1つの理由である.また,性能解析を目的としたインタプリタ方式 のシミュレータに関しては,性能が公表されたものが多い.我々のインタプリタの設計経 験と比べるとこれらのスローダウンが大きいことが 2 つ目の理由である.C コンパイラが 生成した機械命令を調査でき,ホストのプロセッサのパイプライン構造が概略でも理解で きれば,ある程度のチューニングは可能となる.RISCプロセッサの構造は一般に類似性が あるため,特定のホストへのチューニング手法も他ホストにも共通な効果があると考える.

ここからは,具体的な着眼点について述べる.

一般にインタプリタとして公開されているC言語のソースコードには,switch~ case ~

break 文を用いた記述が多いようである.この記述は間接分岐をするコードに変換される.

分岐先で行う処理をコンパイラが最適化することになるが,その最適化の対象範囲をコン パイラが定めることになるが,コードの塊が大きくなるとその最適化による性能向上が困 難になると考える.そこで,命令の種類ごとに関数にすれば,コンパイラが対象とする最 適化の範囲が定まり確実に最適化が行われる.個々の関数間のコード共有がされなくなる が,インタプリタのコード量は元々小さいため命令キャッシュメモリに収まり問題にはな らない.

C コンパイラはパイプラインの最適化として,命令の順番を入れ替えるリソースのスケ ジューリングを行っている.しかし,プログラムの処理単位と次の処理単位との関係を的 確に把握できない場合や,グローバル変数のアクセスが多いと,リソースのスケジューリ ングが期待したほど行われないようである.その結果,コンパイル後のホストのコードで は命令間の並列動作や連続動作ができなくなり処理性能が低下すると考える.そこで,次 のように考えた.

・ コンパイラが生成しやすい単位にプログラムの処理を別ける.具体例としては,関数に 別けてコンパイラがその範囲のみを見れば済むようにする.

・ コンパイラが変数をレジスタに割り付けられるように,変数の制約を緩和する.グロー バル変数が関数内のある部分で頻繁にアクセスされ更にシングルスレッド用にコンパ イルされる条件では,グローバル変数アクセスにメモリだけではなくレジスタも使って アクセスをするように最適化が行われることが多い.しかし,その関数から他の関数を 呼び出して戻ってきたときには他の関数内でそのグローバル変数が変更される可能性 があるため,実際に変更する関数がない場合でもコンパイラは判断できずレジスタを 使った最適化がされない.そのため余分なメモリアクセスが発生し高速化を阻む.この ような場合には,グローバル変数のほかにコピーとして関数内にローカル変数を持ち,

書込みは両方に行い読出しはローカル変数から行うようにプログラム記述をする.ロー

カル変数はレジスタに割り付けられる可能性が高いため,パイプラインストール要因と なるメモリ読出しは行わず高速なレジスタから読出しが行われる.グローバル変数への 書込みは,通常ほかの処理と並行して行われるのでその処理時間は隠ぺいされやすい.

・ レジスタが不足するためにローカル変数をメモリ割付けしてアクセスするようにコン パイルされる場合には,プログラムの記述をレジスタが足りるように軽い処理に分割す る.インタプリタの処理には,実際の出現頻度の低いが複雑な処理が結構ある.それら のために,多くの変数や中間変数が必要となりレジスタ不足が生じやすくなる.このよ うな場合には典型動作を除いた処理を別の関数にするなど単純な処理と複雑な処理を 分離し,レジスタ不足を回避することにより典型処理を高速化できる.

・ 間接分岐命令があると一般に命令キューからの命令供給が途切れるため,その分岐後の 命令列で発生するパイプライン乱れを吸収できなくなりパイプラインストールが発生 しやすくなる.そこで,命令処理関数への分岐実行直後の数命令がよどみなく流れるよ うにする.具体例として,命令処理関数の例を挙げる.加算を行うADD命令などの命 令処理では,インタプリタはレガシーISAのレジスタが格納されているメモリ配列から データ値を読み出すが,その前に命令コードが格納された変数からレジスタフィールド の切り出す必要がある.レガシーレジスタ2個分のメモリ読出しはパイプラインとして 連続動作できる可能性があるが,命令コードの読出しが終わらないとレジスタフィール ドの切り出しをする命令がストールし,それに続くレガシーレジスタのメモリ読出し命 令のディスパッチもできなくなる.RISC の場合には命令語長などの関係から,命令 コードの格納された変数やレガシーレジスタの格納された配列変数のアドレス計算も 必要となる場合もあり,それらもパイプラインストール要因となる場合が多い.これら のストールを回避する手段は,メモリ参照が不要となるように予めホストのレジスタに データを埋め込むことであり,関数呼出しの引数として渡すなどの方法で対応できる.

・ インタプリタでは,各レガシー命令に対応した処理動作が終わりコアループ処理に戻る と,そこでもパイプラインストールを発生しやすい.具体的には,前者でセットしたフ ラグ類を後者で参照するために,リードアフターライトのパイプライン干渉が発生しや すい.これもレジスタ渡しで解決できる.

・ コアループでは,命令コードのデコードは分岐命令で実行する.このときに命令のタイ プによりフィールドの切り出し位置や回数が異なるため,条件付分岐命令を使って判定 を行うことが多い.しかし,マイクロプロセッサの分岐予測はプログラムカウンタやス タックポインタなどの履歴を用いた予測であり,変数のデータ値を用いた分岐予測まで 行っていない.そのため,インタプリタでは一般のプログラムに比べて分岐予測ミスが 発生しやすい.また,一般のプログラムではレジスタ間の演算命令に比べてアドレスオ フセット付きのメモリアクセス命令や即値を使った命令の頻度が比較的に高いという 知見から,インタプリタ処理では 1 つの命令フィールドのみの命令デコードで済む確 率が高いという予見ができる.この両者から,命令デコード方式を評価して最近のマイ クロプロセッサに適した方式を選定する必要があると考える.

ここからは,本研究の新規性と有効性について述べる.

まず,C言語記述のインタプリタ性能に関して,性能向上を評価した研究で公開されたも のは珍しく文献から探すことができないため,新規性または有効性があると考える.なお,