(57)【要約】【課題】  多重ループ内のデータストリームに対して、プリフェッチ起動命令を連続的に参照される最も外側のループの直前に挿入することにより、プリフェッチ起動命令の実行回数を削減してプログラム実行の高速化を図る。【解決手段】  ループに属するプリフェッチ対象データに対して、データが属するループの外側ループを順に辿り、そのループより内側の全ループのイタレーション間で対象データが連続的にアクセスされるようなループのうち最も外側のループを検出し、検出したループ全体で参照されるデータストリームに対するプリフェッチ起動命令を生成して挿入する。【選択図】  図１
2006330813.tif 000002
【特許請求の範囲】
【請求項１】
ソースプログラムをオブジェクトコードに変換するコンパイラ装置であって、
前記ソースプログラムを解析し、当該ソースプログラムが備える多重ループのそれぞれのループについてループ表を生成するループ表生成手段と、
前記ループの中で、当該ループが処理対象とするデータストリームが連続して参照されるループの中で、最も外側のループを抽出する連続参照ループ抽出手段と、
前記連続参照ループ抽出手段で抽出されたループの直前に、メモリ上のデータを予めキャッシュ上に転送しておくプリフェッチ処理の開始を、当該プリフェッチ処理の対象とするデータストリームを指定して指示するプリフェッチ起動命令を挿入しオブジェクトコードを生成するオブジェクトコード生成手段と、を備えること
を特徴とするコンパイラ装置。
【請求項２】
請求項１記載のコンパイラ装置であって、
前記連続参照ループ抽出手段は、
前記ループ表に従って、内側のループから順に、判別対象ループとして当該判別対象ループが処理対象とするデータストリームが、当該判別対象ループの外側ループのうち最も内側のループ（近接外側ループ）のイタレーション間で連続して参照されるか否かを判別し、
連続して参照されると判別された場合、当該近接外側ループを前記判別対象ループとして前記判別を、前記ループ表の全てのループについて繰り返し、最後のループを前記最も外側のループとして抽出し、
連続して参照されないと判別された場合、当該判別対象ループを前記最も外側のループとして抽出すること
を特徴とするコンパイラ装置。
【請求項３】
メモリ上のデータを予めキャッシュ上に転送しておくプリフェッチ処理を行う機構を備えたプロセッサが、記憶装置に格納された多重ループを有するソースプログラムに対し、前記プリフェッチ処理の対象とするデータストリームを指定して前記プリフェッチ処理の開始を指示するプリフェッチ起動命令を挿入しオブジェクトコードを生成する方法であって、
前記プロセッサが前記ソースプログラムを解析し、前記多重ループの各ループのループ表を生成するループ表生成ステップと、
前記ループ表に従って、内側のループから順に全てのループについて、当該ループが処理対象とするデータストリームが連続して参照されるか否か判別し、連続して参照されると判別されたループの中で、最も外側のループを、当該ループの直前に前記プリフェッチ起動命令を挿入すべきループと決定するプリフェッチ起動命令挿入位置決定ステップと、
前記プリフェッチ起動命令挿入位置決定ステップにおいて決定されたループの直前に当該プリフェッチ起動命令を挿入し、オブジェクトコードを生成するオブジェクトコード生成ステップと、
を備えることを特徴とするオブジェクトコード生成方法。
【請求項４】
メモリ上のデータを予めキャッシュ上に転送しておくプリフェッチ処理を行う機構を備えたプロセッサが、記憶装置に格納された多重ループを有するソースプログラムに対し、前記プリフェッチ処理の対象とするデータストリームを指定して前記プリフェッチ処理の開始を指示するプリフェッチ起動命令を直前に挿入するループを決定するプリフェッチ起動命令挿入位置決定方法であって、
前記プロセッサが、前記記憶装置に格納されたソースプログラムのループを解析し、当該解析結果に従って、最も内側のループから順に、前記プリフェッチ処理の対象となるデータストリームを処理対象として有するループ全てについて、
１）当該ループ内にプリフェッチ処理の対象とすべきデータストリームがあるか否かを判別するデータ判別ステップと、
２）前記データストリームがあった場合、当該ループに外側ループがあるか否かを判別するループ位置判別ステップと、
３）当該ループに外側ループがあった場合、当該データストリームが前記外側ループのイタレーション間で連続であるか否かを判別する連続性判別ステップと、を繰り返し、
前記ループ位置判別ステップで、当該ループに外側ループがないと判別された場合、または、前記連続性判別ステップにおいて当該データストリームが連続でないと判別された場合、当該ループを前記プリフェッチ起動命令を直前に挿入するループと決定すること
を特徴とするプリフェッチ起動命令挿入位置決定方法。
【請求項５】
メモリ領域に連続的に配置されるデータストリームへの参照が、多重ループを備える記憶装置に格納されたソースプログラムにおいて判定対象ループの外側ループの内最も内側ループ（近接外側ループと呼ぶ。）のイタレーション間で連続であるか否かを判定する連続性判定方法であって、
プロセッサが前記記憶装置に格納されたソースプログラムを解析し、当該解析結果を用いて、前記判定対象ループのループ回数と前記データストリームが当該ループのイタレーション毎に参照するアドレスの差を要素数で示したストライドとの積を判定対象ループストライドサイズとして算出する判定対象ループストライド算出ステップと、
プロセッサ前記記憶装置に格納されたソースプログラムを解析し、当該解析結果を用いて、前記近接外側ループにおける、前記データストリームに対する前記ストライドを外側ループストライドサイズとして取得する外側ループストライド取得ステップと、
プロセッサが、前記判定対象ループストライドサイズと前記外側ループストライドサイズとを比較し、両者が合致しない場合連続であると判定する連続性判定ステップと、を備えること
を特徴とする連続性判定方法。
【請求項６】
コンピュータを、
ソースプログラムを解析し、当該ソースプログラムが備える多重ループのそれぞれのループについてループ表を生成するループ表生成手段と、
前記ループの中で、当該ループが処理対象とするデータストリームが連続して参照されるループの中で、最も外側のループを抽出する連続参照ループ抽出手段と、
前記連続参照ループ抽出手段で抽出されたループの直前に、メモリ上のデータを予めキャッシュ上に転送しておくプリフェッチ処理の開始を、当該プリフェッチ処理の対象とするデータストリームを指定して指示するプリフェッチ起動命令を挿入しオブジェクトコードを生成するオブジェクトコード生成手段と、として機能させるためのプログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、コンパイル技術に関し、特に、キャッシュを備える計算機におけるプリフェッチ命令挿入技術に関する。
【背景技術】
【０００２】
近年、命令レベルの並列度や動作周波数の向上によりマイクロプロセッサの性能は飛躍的に向上している。一方、計算機の主記憶を構成するDRAMの性能向上は低いレベルに留まっている。この結果、主記憶参照に要するサイクル数は増加する傾向にある。
【０００３】
この問題を解決するために、従来のシステムでは、データ参照の局所性に着目して、主記憶と比較して小容量ではあるものの高速なメモリ（キャッシュ）を配置し、最近参照したデータをキャッシュ上に置くことによって主記憶参照の回数を減らす方式を採ってきた。しかし、数値計算処理などの大規模なデータを使用する計算では、データ参照の局所性が低いためキャッシュミスが多発し、主記憶参照によって生じる待ち時間がプログラムの実行性能にあたえる影響は大きいものとなる。
【０００４】
このような大規模データに対するキャッシュミスを回避するため、主記憶からキャッシュへデータを先行的に読み出すプリフェッチと呼ばれる技術がある。プリフェッチを実現する方式には、ハードウェアで実現する方式、ソフトウェアで実現する方式、両者を組み合わせたハイブリッド方式がある。
【０００５】
ソフトウェアによりプリフェッチを行う方式では、必要となる命令またはデータを該当する命令の実行前に主記憶からキャッシュへ転送するプリフェッチ命令をプロセッサの命令セットに用意し、コンパイラによってソースプログラムのコンパイル時にプリフェッチ命令をソースプログラムの一部に挿入する。
【０００６】
コンパイラがプリフェッチ対象とする典型的なケースは、ループ内で参照される連続アクセスである。例えばループ内に配列参照Ａ［ｉ］（ｉはループ制御変数）があった場合、prefetch（＆Ａ［ｉ+ｄ］）のようなプリフェッチ命令をループ内に挿入することにより、ｄイタレーション後に参照するデータをプリフェッチする。ここでｄの値は、ループの１回の繰り返しにかかるサイクル数と、主記憶参照に要するサイクル数に基づき計算する。
【０００７】
ハードウェアによるプリフェッチ方式では、プロセッサはメモリ参照のアドレスを記録して連続的なアドレスのアクセスを検出し、プリフェッチ対象のデータストリームとして登録する機構を備えている。また、登録したデータストリームに対しては、ストリームのデータが参照されるタイミングに合わせて、先行的にデータのプリフェッチを続ける機構を備える。これらの機構により、メモリを連続的に参照するデータストリームに対して、プログラムの実行中にプロセッサによる自動的なプリフェッチ処理が実施される。
【０００８】
ハイブリッド方式では、データストリームを指定するプリフェッチ命令（以後、プリフェッチ起動命令と呼ぶ）を用意する。コンパイラは、コンパイル時にソースプログラムを解析し、メモリを連続的にアクセスするデータストリームを検出すると、プリフェッチ起動命令を生成して初期アドレスやストリームの長さなどを指定する。プリフェッチ起動命令で指定されたデータストリームに対して、キャッシュラインを順次プリフェッチしていく処理は、上記のハードウェア方式と同様に、ハードウェアにより実行時に自動的に実施される。
【０００９】
図６にハイブリッド方式によるプリフェッチを行うためのコード例を示す。本例はＣ言語で記述され、配列ａを連続的にアクセスするループを備える。ここで配列ａの各要素は４バイトであるとする。ハイブリッド方式では、配列ａのアクセスに対するプリフェッチ起動命令が本ループの直前に挿入される。図６では、プリフェッチ起動命令をstreamprefetchという記述により、ソースイメージで示している。streamprefetchの引数には、ループの初回イタレーションにおいて参照される配列ａのアドレス＆ａ［０］、データストリームのサイズ即ちループ全体で参照される要素数を示すＮ、データストリームが繰り返しごとに参照するアドレスの差を示す４、何要素分先読みするかを示す１が指定されている。
【００１０】
このようなプリフェッチ方式に関しては、非特許文献１に記載されている。
【００１１】
【非特許文献１】Andy D. Pimentel, Louis O. Hertzberger, Pieter Struik, and Pieter van der Wolf, Hardware versus Hybrid Data Prefetching in Multimedia Processors: A Case Study', In Proc. of the IEEE Int. Performance, Computing and Communications Conference, Feb. 2000.
【発明の開示】
【発明が解決しようとする課題】
【００１２】
ハイブリッド方式のプリフェッチでは、コンパイラがプリフェッチ対象のデータストリームを検出し、プリフェッチ起動命令をオブジェクトコードに挿入する必要がある。コンパイラのプリフェッチ処理は対象データが属するループを対象として行い、ループの開始前にプリフェッチ起動命令が実行されるようなコードを生成する。
【００１３】
例えば、図７のソースプログラムを考える。本例はＣ言語で記述され、ｉ、ｊ、ｋの３重ループ中に配列ａ、ｂの参照がある。ここで配列ａに着目すると、ａの参照が属する最内側ループ（ｋループ）に対する解析で、ａ［ｉ］［ｊ］［０］からａ［ｉ］［ｊ］［９９］までの要素を連続的にアクセスすることから、コンパイラはこの範囲をアクセスするデータストリームをプリフェッチ対象と認識し、図８に示すようにｋループの直前にプリフェッチ起動命令を挿入する。
【００１４】
ところが、配列ａのアクセスを３重ループ全体で考えると、本例の３重ループにおいてはａ［０］［０］［０］からａ［９］［９９］［９９］まで配列ａの全要素をメモリ配置に従って順にアクセスしている。すなわち、配列ａについては、この範囲全体を１つのデータストリームと考えることができる。この場合、プリフェッチ起動命令はｉループの開始前に実行すればよいが、従来の方法では、コンパイラはｋループの開始前にプリフェッチ起動命令を挿入する。従って、ｋループの実行ごとにプリフェッチ起動命令が実行されることとなる。従来の方法では、本来不要であるプリフェッチ起動命令の実行ごとに、プリフェッチストリームの登録や、先読みするデータのプリフェッチなど、プリフェッチの立ち上げオーバーヘッドがかかるため、実行時間の増加につながるという問題がある。
【００１５】
本発明は、上記事情に鑑みてなされたもので、ハイブリッド方式のプリフェッチ機構を備えたプロセッサに対するコード生成方法において、多重ループ内で参照されるデータストリームに対して、プリフェッチ起動命令を適切な位置に挿入することにより、プリフェッチ起動命令の実行回数を削減し、オブジェクトコードの実行性能向上を図ることを目的とする。
【課題を解決するための手段】
【００１６】
本発明は、ループに属するプリフェッチ対象データに対して、データが属するループの外側ループを順に辿り、そのループより内側の全ループのイタレーション間で対象データが連続的にアクセスされるようなループのうち最も外側のループを検出し、検出したループ全体で参照されるデータストリームに対するプリフェッチ起動命令を生成して挿入する。
【００１７】
具体的には、ソースプログラムをオブジェクトコードに変換するコンパイラ装置であって、前記ソースプログラムを解析し、当該ソースプログラムが備える多重ループのそれぞれのループについてループ表を生成するループ表生成手段と、前記ループの中で、当該ループが処理対象とするデータストリームが連続して参照されるループの中で、最も外側のループを抽出する連続参照ループ抽出手段と、前記連続参照ループ抽出手段で抽出されたループの直前に、メモリ上のデータを予めキャッシュ上に転送しておくプリフェッチ処理の開始を、当該プリフェッチ処理の対象とするデータストリームを指定して指示するプリフェッチ起動命令を挿入しオブジェクトコードを生成するオブジェクトコード生成手段と、を備えることを特徴とするコンパイラ装置を提供する。
【発明の効果】
【００１８】
本発明によれば、ハイブリッド方式のプリフェッチ機構を備えたプロセッサに対するコード生成方法において、多重ループ内で参照されるデータストリームに対して、プリフェッチ起動命令を適切な位置に挿入することにより、プリフェッチ起動命令の実行回数を削減し、オブジェクトコードの実行性能向上を図ることができる。
【発明を実施するための最良の形態】
【００１９】
＜＜第一の実施形態＞＞
以下、図面を用いて本発明の実施の形態について説明する。
【００２０】
図１は、本実施形態によるコンパイラが稼動する計算機システムの構成図である。本計算機システムは、ＣＰＵ２０１、ディスプレイ装置２０２、キーボード２０３、主記憶装置２０４、および外部記憶装置２０５を備える。キーボード２０３は、ユーザからのコンパイラ起動命令などの入力を受け付ける。ディスプレイ装置２０２はコンパイラ終了メッセージおよびエラーメッセージなどを表示する。外部記憶装置２０５には、ソースプログラム２０６とオブジェクトプログラム２０７が格納される。主記憶装置２０４には、コンパイラプログラム２０８、コンパイル過程で必要となる中間コード２０９とループ表２１０とが格納される。コンパイル処理は、ＣＰＵ２０１がコンパイラプログラム２０８を実行することにより行われる。
【００２１】
図２に、図１のシステムで稼動するコンパイラプログラム２０８の処理手順を示す。
【００２２】
コンパイラプログラム２０８は、ソースプログラム２０６を読み込み、構文解析を行い、中間コード２０９を出力する（ステップ３０１：構文解析）。
【００２３】
次に、中間コード２０９を解析し、ソースプログラム２０６に含まれるループの集合を求め、ループ表２１０に記録する（ステップ３０２：ループ解析）。ループを解析し、ループ表２１０を生成する方法に関しては、例えば、Michael Wolfe著「High Performance Compilers for Parallel Computing」、Addison-Wesley Publishing Company, 1996の６７頁に記載されている。
【００２４】
次に、コンパイラプログラム２０８は、各ループに対し、プリフェッチ処理を行う。まず、プリフェッチ処理が未処理であるループの有無を判定する（ステップ３０３）。判定は、例えば、ループ表に処理済みの有無を記録する欄を設け、その欄の記録を参照するなどの方法により行う。また、ループ表のループ番号順に処理を進めるよう構成してもよい。
【００２５】
未処理のループがある場合、未処理のループから１つループを取り出す（ステップ３０４）。取り出したループを対象にプリフェッチ処理を行った後（ステップ３０５）、ステップ３０３へ戻る。ステップ３０５での処理の詳細については、本発明の特徴となる部分であるので、後述する。
【００２６】
一方、コンパイラプログラム２０８は、ステップ３０３において未処理のループがないと判定した場合、ステップ３０６へ進み、中間コード２０９をオブジェクトプログラム２０７に変換し、出力する（ステップ３０６：コード生成）。
【００２７】
ここで、上記ステップ３０２のループ解析により生成されるループ表２１０について説明する。図３は、ループ表２１０の一例である。ループ表２１０には、ループ番号５０１、外側ループ５０２、制御変数５０３、初期値５０４、終値５０５、増分値５０６、ループ回数５０７が格納される。
【００２８】
ループ番号５０１はコンパイラ内でループを識別するための番号である。外側ループ５０２は、対象ループを取り囲むループのうち最も内側のループのループ番号である。対象ループが最も外側のループの場合、「なし」が外側ループ５０２として登録される。制御変数５０３は、対象ループの繰り返しを制御するループ制御変数である。初期値５０４、終値５０５、増分値５０６は、それぞれ、制御変数５０３（ループ制御変数）の初期値、終値、繰り返しごとの増分である。ループ回数５０７は、ループの繰り返し回数である。ループ回数５０７は制御変数５０３（ループ制御変数）の初期値、終値、増分値から求められる。
【００２９】
次に、上述のステップ３０５における１つのループに対するプリフェッチ処理の処理手順を、説明する。図４は、本実施形態のプリフェッチ処理の処理フローである。以下の処理はコンパイラプログラム２０８に従って、ＣＰＵ２０１が行うものである。
【００３０】
処理対象ループ中に未処理かつプリフェッチの対象とすべき配列参照があるかどうかを判別する（ステップ１０１）。なお、各配列参照は、その参照を囲む最も内側のループで処理対象とするものとする。従って、対象ループに直接属する配列参照が処理対象となる。例えば、図７に示すソースプログラムでは、制御変数がｉおよびｊのループには、直接属する配列参照はない。一方、制御変数がｋのループには、ｓ＝ｓ＋ａ［ｉ］［ｊ］［ｋ］＋ｂ［ｉ］［ｊ］［ｋ］；で示される配列参照を含む処理ステップがあり、直接属する配列参照があると判別される。
【００３１】
また、本実施形態のプリフェッチ処理では、参照アドレスが連続的なデータストリームを対象とするため、繰り返しごとの参照アドレスの増分が一定で、その値が一定値（例えば、キャッシュラインサイズ）以下であるなどの判定基準も考慮し、対象配列を決める。
【００３２】
未処理の配列参照がある場合、その中から配列参照を１つ取り出しＡとする（ステップ１０２）。
【００３３】
変数ＬＯＯＰを処理対象ループに初期化する（ステップ１０３）。ここでは、ループ表２１０の処理対象ループのループ番号５０１を変数ＬＯＯＰに代入する。以後、変数ＬＯＯＰで示される処理対象のループを、ＬＯＯＰと呼ぶ。
【００３４】
ＬＯＯＰの外側ループの有無をループ表２１０の外側ループ５０２の値により判定し（ステップ１０４）、外側ループがある場合、外側ループを取り出す（ステップ１０５）。ステップ１０４で外側ループがないと判定した場合、ステップ１０８へ進む。
【００３５】
次に、配列Ａが外側ループ５０２のイタレーション間で連続であるかどうかを判定する（ステップ１０６）。本ステップの判定手順の詳細は後で説明する。ステップ１０６で連続でないと判定した場合は、ステップ１０８へ進む。連続であると判定した場合は、ステップ１０７へ進んで変数ＬＯＯＰをＬＯＯＰの外側ループ５０２に更新し、ステップ１０４へ戻り外側ループを辿って判定する処理を繰り返す。
【００３６】
ここまでの処理により、ステップ１０８への到達時には、ＬＯＯＰおよびその内側の各ループから構成されるループネストの実行中、配列Ａは連続的に参照されることになる。
【００３７】
そして、変数ＬＯＯＰで示されるループの実行により参照される配列Ａのデータ長を計算する（ステップ１０８）。配列Ａは連続的に参照されるので、ここで計算するデータ長は、配列Ａの添え字を解析してＬＯＯＰに関するストライドを求め、本ストライドとＬＯＯＰのループ回数の積により求めることができる。ここでストライドは、データストリームが繰り返しごとに参照するアドレスの差を要素数で示したものとする。
【００３８】
配列Ａのプリフェッチ起動命令を生成し、ＬＯＯＰの直前に挿入する（ステップ１０９）。プリフェッチ起動命令は、配列Ａの初期アドレス、ステップ１０８で求めたデータ長などを引数として生成する。配列Ａの初期アドレスは、配列Ａの添え字に各ループ制御変数の初期値５０４を代入することなどによって求めることができる。
【００３９】
次に、上記ステップ１０６において外側ループイタレーション間の連続性を判定する判定処理の手順を説明する。図５は、本判定処理を説明するためのフローである。本判定処理もコンパイラプログラム２０８をＣＰＵ２０１が実行することにより実現される。
【００４０】
はじめに、本判定処理で用いる変数を初期化する（ステップ４０１）。具体的には、変数ＩＮＮＥＲＬＯＯＰに配列Ａを含む現在プリフェッチ処理中のループ、すなわち、ステップ３０４で取り出したループのループ番号５０１を登録し、変数ＯＵＴＥＲＬＯＯＰにステップ１０６で判定対象とする外側ループのループ番号５０１を登録する。以後、変数ＩＮＴＥＲＬＯＯＰで示されるループをＩＮＴＥＲＬＯＯＰと、変数ＯＵＴＥＲＬＯＯＰで示されるループをＯＵＴＥＲＬＯＯＰと呼ぶ。ＲＥＦＳＩＺＥは配列Ａの参照サイズを計算するための変数で、配列Ａを含むループのループ回数５０７と配列Ａを含むループにおける配列Ａのストライドとの積を初期値に設定する。
【００４１】
ループ表２１０からＩＮＮＥＲＬＯＯＰの外側ループ５０２を取り出し、ＯＵＴＥＲＬＯＯＰと一致するかどうか判別する（ステップ４０２）。一致する場合にはステップ４０５へ進む。一致しない場合には、取り出した外側ループ５０２をＩＮＮＥＲＬＯＯＰに登録し（ステップ４０３）、ステップ４０４へ進む。
【００４２】
ＲＥＦＳＩＺＥにＩＮＮＥＲＬＯＯＰのループ回数を掛けて更新した後（ステップ４０４）ステップ４０２へ戻る。
【００４３】
ステップ４０２、４０３、４０４を繰り返すことにより、ＯＵＴＥＲＬＯＯＰの内側のループを実行した場合、すなわち、ＯＵＴＥＲＬＯＯＰの１イタレーションを実行した場合に参照される配列ＡのデータサイズがＲＥＦＳＩＺＥに設定される。
【００４４】
一方、ステップ４０２において一致する場合、ＯＵＴＥＲＬＯＯＰの１イタレーションごとの配列Ａの参照アドレスの差が何要素分であるかを求め、変数ＯＵＴＥＲＳＴＲＩＤＥに設定する（ステップ４０５）。
【００４５】
そして、ＯＵＴＥＲＳＴＲＩＤＥとＲＥＦＳＩＺＥの差を計算し、この差の絶対値がα以下であるかどうかを判定する（ステップ４０６）。ここでαには、ハードウェアによるプリフェッチ動作が中断されないような小さな値を選ぶ。例えば、αに１キャッシュラインに含まれる配列要素数などを設定する。
【００４６】
ステップ４０６で差の絶対値がα以下であれば、連続であると判定し（ステップ４０７）、処理を終了する。一方、α以下でなければ、連続でないと判定し（ステップ４０８）、処理を終了する。
【００４７】
以上、本実施形態のプリフェッチ処理について説明した。
【００４８】
次に、図７に示すソースプログラムに、本実施形態のプリフェッチ処理を適用した場合の処理手順を説明する。以下についても、コンパイルプログラム２０８に従って、ＣＰＵ２０１が処理を行う。
【００４９】
構文解析３０１の後、ループ解析３０２において図３に示すループ表を作成する。ここで、本実施形態では、ループ番号５０１は外側ループから順に１、２、３と付与される。
【００５０】
ステップ３０３、３０４において、未処理ループとして、ループ１、ループ２、ループ３が順に取り出される。しかし、ループ１およびループ２には、直接属する配列参照がないため、プリフェッチ処理３０５において、図４のステップ１０１で処理が終了する。すなわち、プリフェッチ処理は適用されない。一方、ループ３は、直接属する配列参照があり、プリフェッチ処理が行われる。以下では、ループ３に対するプリフェッチ処理３０５について説明する。
【００５１】
ステップ１０２において、まず配列参照ａ［ｉ］［ｊ］［ｋ］を取り出す。ステップ１０３で変数ＬＯＯＰにループ３を設定する。ステップ１０４でループ３の外側ループ５０２はループ２であるので、ステップ１０５へ進み、ループ２を取り出す。ステップ１０６では図５の処理手順に従い、配列参照ａ［ｉ］［ｊ］［ｋ］がループ２のイタレーション間で連続であるか否かを判定する。
【００５２】
ステップ４０１において、変数ＩＮＮＥＲＬＯＯＰにループ３を、ＯＵＴＥＲＬＯＯＰにループ２を設定する。配列参照ａ［ｉ］［ｊ］［ｋ］のループ３におけるストライドは１要素、ループ回数は１００であるので、ＲＥＦＳＩＺＥに１００（１×１００）を設定する。
【００５３】
ステップ４０２において、ループ３の外側ループはループ２でＯＵＴＥＲＬＯＯＰと一致するので、ステップ４０５へ進む。
【００５４】
ステップ４０５でループ２における配列参照ａ［ｉ］［ｊ］［ｋ］のストライドを計算する。ループ２が１回実行されるごとに制御変数ｊが１増加する。配列参照ａ［ｉ］［ｊ］［ｋ］において２番目の次元の添え字がｊであり、配列ａの宣言ａ［１０］［１００］［１００］から３番目の次元のサイズのサイズが１００であるので、ループ２における配列参照ａ［ｉ］［ｊ］［ｋ］のストライドは１００である。
【００５５】
ここでは、αを例えば０とする。ステップ４０６では、ＯＵＴＥＲＳＴＲＩＤＥとＲＥＦＳＩＺＥはともに１００であるので、ステップ４０６の判定を満たす。従って、ステップ４０７へ進み、連続であると判定し、判定処理を終了し、図４のステップ１０７へ進む。
【００５６】
ステップ１０７では、変数ＬＯＯＰにループ２を設定し、ステップ１０４へ戻る。ループ２には外側ループ５０２としてループ１があるので、ステップ１０５でループ１を取り出す。ステップ１０６では、配列参照ａ［ｉ］［ｊ］［ｋ］がループ１のイタレーション間で連続であるかどうかを判定する。
【００５７】
ステップ４０１において、変数ＩＮＮＥＲＬＯＯＰにループ３を、変数ＯＵＴＥＲＬＯＯＰにループ１を、配列参照ａ［ｉ］［ｊ］［ｋ］のループ３におけるストライドは１要素、ループ回数は１００であるため、変数ＲＥＦＳＩＺＥに１００を設定する。
【００５８】
ステップ４０２において、ループ３の外側ループはループ２でＯＵＴＥＲＬＯＯＰと一致しないので、ステップ４０３で変数ＩＮＮＥＲＬＯＯＰにループ２を設定する。
【００５９】
ステップ４０４において、ループ２のループ回数は１００であるので、ＲＥＦＳＩＺＥを１００×１００=１００００に更新し、ステップ４０２へ戻る。
【００６０】
ステップ４０２において、ループ２の外側ループ５０２はループ１でＯＵＴＥＲＬＯＯＰと一致するので、ステップ４０５へ進む。
【００６１】
ステップ４０５でループ１における配列参照ａ［ｉ］［ｊ］［ｋ］のストライドを計算する。ループ１が１回実行されるごとに制御変数ｉが１増加する。ａ［ｉ］［ｊ］［ｋ］において１番目の次元の添え字がｉであり、配列ａの宣言ａ［１０］［１００］［１００］から２番目および３番目の次元のサイズがそれぞれ１００であるので、ａのストライドは１００×１００=１００００である。
【００６２】
ステップ４０６において、ＯＵＴＥＲＳＴＲＩＤＥとＲＥＦＳＩＺＥはともに１００００であるので、αが０の場合、本判定を満たし、ステップ４０７へ進む。そして、連続であると判定し、図４のステップ１０７へ進む。
【００６３】
図４のステップ１０７では、変数ＬＯＯＰにループ１を設定してステップ１０４へ戻る。
【００６４】
ステップ１０４では、ループ１の外側ループがないため、ステップ１０８へ進む。
【００６５】
ステップ１０８では、ループ１で参照される配列参照ａ［ｉ］［ｊ］［ｋ］のデータ長を計算する。ループ１におけるストライドは１００００、ループ１のループ回数は１０であるのでデータ長を１０００００とする。
【００６６】
ステップ１０９では、プリフェッチ起動命令streamprefetch（＆ａ［０］［０］［０］, １０００００, ４, １）を生成する。ここで、本命令の第１引数はループで参照される初期アドレス、第２引数はステップ１０８で求めたデータ長、第３引数は配列ａ［ｉ］［ｊ］［ｋ］の参照ごとのアドレスの差をバイト数で示した値である。第４引数はａ［ｉ］［ｊ］［ｋ］が参照されたときに何要素先をプリフェッチするかを示す値である。本実施形態ではこの値を１とする。生成したプリフェッチ起動命令をループ１の直前に挿入する。
【００６７】
次に、ステップ１０１へ戻り、ループ内の次の配列参照ｂ［ｉ］［ｊ］［ｋ］の処理を行う。ステップ１０５でループ３の外側ループ５０２であるループ２を取り出し、ステップ１０６で、ループ３がループ２のイタレーション間で連続であるかを判定する。本判定処理は配列ａで説明したのと同様であり、連続であると判定してステップ１０７へ進んで変数ＬＯＯＰをループ２に更新する。
【００６８】
ステップ１０４へ戻り、ステップ１０５でループ２の外側ループ５０２であるループ１取り出し、ステップ１０６で、ループ２がループ１のイタレーション間で連続かどうかを判定する。
【００６９】
ステップ４０１において、変数ＩＮＮＥＲＬＯＯＰにループ３を、変数ＯＵＴＥＲＬＯＯＰにループ１を、ＲＥＦＳＩＺＥに１００を設定する。
【００７０】
ステップ４０２において、ループ３の外側ループ５０２はループ２でＯＵＴＥＲＬＯＯＰと一致しないので、ステップ４０３で変数ＩＮＮＥＲＬＯＯＰにループ２を設定する。
【００７１】
ステップ４０４において、ループ２のループ回数は１００であるので、REFSIZEを１００×１００=１００００に更新し、ステップ４０２へ戻る。
【００７２】
ステップ４０２において、ループ２の外側ループ５０２はループ１でＯＵＴＥＲＬＯＯＰと一致するので、ステップ４０５へ進む。
【００７３】
ステップ４０５でループ１における配列参照ｂ［ｉ］［ｊ］［ｋ］のストライドを計算する。ループ１が１回実行されるごとに制御変数ｉが１増加する。配列参照ｂ［ｉ］［ｊ］［ｋ］において１番目の次元の添え字がｉであり、配列ｂの宣言ｂ［１０］［２００］［１００］から２番目の次元のサイズが２００、３番目の次元のサイズが１００であるので、ループ１における配列参照ｂのストライドは２００×１００=２００００である。
【００７４】
ステップ４０６において、ＯＵＴＥＲＳＴＲＩＤＥが２００００、REFSIZEが１００００であるので、両者の差が所定範囲α（＝０）外であるため、ステップ４０８へ進み、連続でないと判定し、図４の処理に戻る。
【００７５】
ここでは、ステップ１０６で連続でないと判定されたので、ステップ１０８へ進み、この時点のＬＯＯＰであるループ２で参照されるｂ［ｉ］［ｊ］［ｋ］のデータ長を計算する。ループ２におけるストライドは１００、ループ２のループ回数は１００であるのでデータ長は１００００である。
【００７６】
ステップ１０９ではプリフェッチ起動命令streamprefetch（＆ｂ［ｉ］［０］［０］, １００００, ４, １）を生成する。生成したプリフェッチ起動命令をループ２の直前に挿入する。
【００７７】
ステップ１０１へ戻り、未処理のプリフェッチ対象配列がないため処理を終了する。
【００７８】
以上で説明したプリフェッチ処理の適用により、図７で示したループに対して、生成されるコードを図９に示す。
【００７９】
図９のコードを従来のプリフェッチ方法による図８のコードと比較すると、図８のコードでは各配列参照ａ［ｉ］［ｊ］［ｋ］およびｂ［ｉ］［ｊ］［ｋ］に対してそれぞれプリフェッチ起動命令が１０×１００=１０００回実行されるのに対して、図９のコードでは配列参照ａ［ｉ］［ｊ］［ｋ］に対するプリフェッチ起動命令の実行は１回、配列参照ｂ［ｉ］［ｊ］［ｋ］に対しては１０回となり、プリフェッチ起動命令の実行回数を大幅に削減することができる。
【００８０】
すなわち、本実施形態によれば、多重ループにおいて連続的に参照されるデータストリームに対して、各外側ループのイタレーション間で連続であるかを判定する手段を設けることにより、連続的に参照されるループ範囲を求め、そのループ開始時にのみプリフェッチ起動命令を実行するコードを生成することができる。これにより、データ参照を含むループの開始前に毎回プリフェッチ起動命令を実行する場合と比較して、キャッシュミスの頻度を増加させることなく、プリフェッチ起動命令の実行回数を削減でき、プログラム実行の高速化が図れる。
【００８１】
本実施形態は、計算機において、オブジェクトプログラムの実行時間を削減する最適化機能を備えたコンパイラに適用できる。
【図面の簡単な説明】
【００８２】
【図１】図１は、本実施形態によるコンパイラが稼動する計算機システムの構成図である。
【図２】図２は、本実施形態のコンパイラプログラムの処理手順を示すフローである。
【図３】図３は、本実施形態のループ表の一例である。
【図４】図４は、本実施形態のプリフェッチ処理の処理フローである。
【図５】図５は、本実施形態の外側ループでの連続性を判定する処理手順を示すフローである。
【図６】図６は、従来技術によるプリフェッチを行うコード例である。
【図７】図７は、ソースプログラムの一例を示す。
【図８】図８は、従来技術による、ソースプログラムに対してプリフェッチ処理を適用したコードの例である。
【図９】図９は、本実施形態による、ソースプログラムに対してプリフェッチ処理を適用したコードの例である。
【符号の説明】
【００８３】
２０１：ＣＰＵ、２０２：ディスプレイ装置、２０３：キーボード、２０４：主記憶装置、２０５：外部記憶装置、２０６：ソースプログラム、２０７：オブジェクトプログラム、２０８：コンパイラ、２０９：中間コード、２２０：ループ表
【図１】
2006330813.tif 000003
【図２】
2006330813.tif 000004
【図３】
2006330813.tif 000005
【図４】
2006330813.tif 000006
【図５】
2006330813.tif 000007
【図６】
2006330813.tif 000008
【図７】
2006330813.tif 000009
【図８】
2006330813.tif 000010
【図９】
2006330813.tif 000011