以下、図面に基づいて、本発明の実施の形態を説明する。以下の実施形態の構成は例示であり、本発明は実施形態の構成に限定されない。
<ハードウェアプリフェッチ機構>
図1から図3は、ハードウェアプリフェッチ機構を説明するための図である。図1は、
ハードウェアプリフェッチ起動の例を示す図である。図1のs1で示すプログラムソースコード(以下、ソースコードともいう)には、DOで始まるjについてのループ処理が記載されている。jのループ処理は、更に、iのループ処理を含む。iのループ処理は、配列A(i,j)を参照する処理を含む。配列A(i,j)の参照により、主記憶装置上の連続領域がアクセスされる。
図1は、更に、ソースコードに対応するキャッシュメモリ(以下、メモリともいう)のアクセスイメージを示す。ハードウェアプリフェッチは、連続領域へのアクセスにより、一定時間後、自動的に起動される。例えば、図1において星印で示されるキャッシュミスが、連続するキャッシュラインで検出されると、次回も連続領域へのアクセスであるとみなして、次のキャッシュラインデータがプリフェッチされる。
図2は、ハードウェアプリフェッチ起動の具体例を示す図である。図2には、図1と同様のソースコードが記載されている。ただし、内側のループ処理における制御変数iは、1から18までの値をとる。配列A(i,j)の1要素は8バイトとする。また、1キャッシュラインの長さは128バイトとする。この場合、1キャッシュラインは16要素を含む。
配列A(i,j)の参照により、8バイト単位で連続領域にアクセスする場合、iが1の場合のアクセスで1回目のキャッシュミスが発生する。キャッシュメモリはキャッシュライン単位でメモリ内容の入替えを管理するため、iが2から16の場合のアクセスは、アクセスするデータが同じキャッシュラインに存在し、キャッシュヒットする。iが17の場合のアクセスでは、アクセスするデータが次のキャッシュラインに割り当てられるため、2回目のキャッシュミスが発生する。
連続領域へのアクセスに対するキャッシュミスか否かは、例えば、キャッシュライン番号によって判断される。連続するキャッシュライン番号に対し、キャッシュミスが複数回発生すると、ハードウェアプリフェッチが起動される。本実施形態は、キャッシュミスが2回発生すると、ハードウェアプリフェッチが起動されるものとして説明される。
図2において、2回目のキャッシュミスが発生することにより、ハードウェアプリフェッチが起動される。ハードウェアプリフェッチの起動により、点線で囲まれたプリフェッチ対象のキャッシュラインが、プリフェッチされる。しかしながら、内側のループ処理は、iが18までで終了し、次のjのループに処理が進む。このため、プリフェッチされたデータは参照されない。
図3は、ハードウェアプリフェッチ停止の具体例を示す図である。図3のs2で示すソースコードには、jのループ処理が記載されている。jが4の倍数でない場合は、iのループ処理が実行される。iのループ処理は、配列A(i,j)を参照する処理を含む。iは1から16までの値をとる。配列A(i,j)の1要素は8バイトとし、1キャッシュラインの長さは128バイトとする。
jが1の場合、4の倍数ではないため、iのループ処理が実行される。iが1の場合のアクセスでキャッシュミスが発生する。iが2から16の場合のアクセスは、アクセスするデータが同じキャッシュラインに存在するため、キャッシュヒットする。
jが2の場合も、iのループ処理が実行される。iが1の場合のアクセスで、2回目のキャッシュミスが発生する。2回のキャッシュミスの発生により、ハードウェアプリフェッチが起動され、次のキャッシュラインのデータがプリフェッチされる。jが3の場合も、iのループ処理が実行される。アクセスするデータがメモリ上にプリフェッチされてい
るため、キャッシュミスは発生しない。
jが4の場合、4の倍数であるため、iのループ処理は実行されない。これにより、連続領域へのアクセスは終了し、アクセスするデータを含むキャッシュラインのキャッシュライン番号は、昇順(又は降順)ではなくなる。この時点でハードウェアプリフェッチは停止する。ハードウェアプリフェッチは、jが5及び6の場合に連続してキャッシュミスが発生するまで起動されない。
なお、図面において、配列の要素は8バイト、1キャッシュラインの長さは128バイトとして説明するが、各サイズに限定はない。また、キャッシュライン番号が連続する複数のキャッシュラインにおいて、2回連続してキャッシュミスが発生した場合に、ハードウェアプリフェッチが起動されるものとして説明したが、キャッシュミスの発生回数は、2回に限定されるわけではない。ハードウェアプリフェッチの起動条件としてのキャッシュミス発生回数の閾値nは、任意であってもよい。
連続領域に対するハードウェアプリフェッチの起動条件において、適切な閾値nは、プログラム内でアクセスされる連続領域の平均的なサイズに依存する。閾値nが適切な値より小さいと、連続領域へのアクセスが終了した後も不要なプリフェッチが実行され、メモリバンド幅が圧迫される場合がある。一方、閾値nが適切な値より大きいと、ハードウェアプリェッチが起動されるまでのウォームアップ時間が延びて、キャッシュミスによる読出し遅延が隠蔽されなくなる。
一定の閾値nを設定してハードウェアプリフェッチを動作させる場合、プログラム内でアクセスされる連続領域のサイズによっては、ウォームアップ時間が経過する前に連続領域へのアクセスが終了し、ハードウェアプリフェッチによる効果が得られない場合がある。例えば、図3において、配列A(i,j)の参照でアクセスされる連続領域のサイズ(18×8バイト)は、キャッシュラインサイズ×2(128バイト×2)より小さい。このため、3番目のキャッシュラインがプリフェッチされるが、次のjの値でのループ処理に進み、別領域へのアクセスとなるため、プリフェッチしたデータはアクセスされず、ハードウェアプリフェッチは無駄となる。
このように、不要なハードウェアプリフェッチの発行によってメモリバンド幅が浪費されたり、連続領域へのアクセスが発生しないためにハードウェアプリフェッチが停止したりすることで、ハードウェアプリフェッチによる効果が得られない場合もある。
なお、本実施形態における図面において、ソースコードの例はFORTRAN言語により記載されるが、他のプログラミング言語であってもよく、各図面の説明は言語に依存しない。また、ハードウェアプリフェッチの起動条件となる連続領域へアクセスは、アドレスの昇順方向に連続する領域へのアクセスであっても、アドレスの降順方向に連続する領域へのアクセスであっても良い。
<キャッシュミスの発生>
図4から図6は、キャッシュミスが発生する例を説明するための図である。図4は、ハードウェアプリフェッチの停止によりキャッシュミスが発生する例を示す図である。図4に示すソースコードには、iのループ処理が記載されている。iのループ処理は、更に、jのループ処理を含む。jのループ処理は、配列A(j)を参照する処理を含む。
配列A(j)は、iについてのループごとに、配列A(j)のデータを含む同じ領域を繰返しアクセスする。図4において、aは、配列A(j)のデータを含む領域である。iが1のとき、配列A(j)のデータへの1回目のアクセスにより、キャッシュミスが複数
回発生すると、ハードウェアプリフェッチが起動される。配列A(j)のデータは、最後までプリフェッチされる。
iが1の場合の処理が終了し、iが2に切り替わると、配列A(j)のデータへのアクセスは先頭に戻り、アクセスする領域が連続でなくなるため、ハードウェアプリフェッチは停止する。また、1回目のアクセスでキャッシュメモリに配置された配列A(j)のデータは、他の変数のデータへのアクセスにより、キャッシュメモリから追い出される場合がある。このため、配列A(j)のデータへの2回目のアクセスの際、配列A(j)のデータがキャッシュメモリから追い出されている場合には、キャッシュミスが発生する。
即ち、配列A(j)のデータへの2回目以降のアクセスの際、ハードウェアプリフェッチは停止し、他の変数のデータへのアクセスにより配列A(j)のデータがキャッシュメモリから追い出されている場合には、キャッシュミスが発生する。
図5は、キャッシュラインの競合によりキャッシュミスが発生する例を示す図である。図5には、図4と同様のソースコードが記載されている。ただし、iのループ処理は、jのループ処理の後、配列B(j)及び配列C(j)を参照する処理を含む。図5において、aは、配列A(j)がアクセスする連続領域である。
ここで、3つの配列A、B、Cは、キャッシュメモリのウェイ数を2として、同一のキャッシュラインに割り当てられているものとする。iがnのとき、配列A(j)のデータへのn回目のアクセスにより、キャッシュミスが複数回発生すると、ハードウェアプリフェッチが起動される。配列A(j)のデータは、最後までプリフェッチされる。
その後、配列B(j)及び配列C(j)のデータがアクセスされると、同一のキャッシュラインに配置されていた配列A(j)のデータは、キャッシュラインから追い出される。このため、iがn+1に切り替わった後、配列A(j)のデータへのn+1回目のアクセスの際、キャッシュミスが発生する。これが交互に繰り返されるため、配列A(j)の先頭にアクセスするたびにキャッシュミスが発生する。
図6は、図5の具体例を示す図である。図6に示すソースコードには、iのループ処理が記載されている。iのループ処理は、更に、jのループ処理を2つ含む。1つめのjのループ処理は、配列A(j)を参照する処理を含み、jは1から17までの値をとる。2つめのjのループ処理は、配列B(j)及び配列C(j)を参照する処理を含み、jは1から1000までの値をとる。
なお、配列A(j)、B(j)及び配列C(j)は、要素数が16*1024/8の倍精度実数
型の配列である。プロセッサのデータキャッシュのウェイのサイズを16Kバイトとすると、配列A、B、Cはウェイのサイズと一致するため、各領域の先頭アドレスは、同じキャッシュライン番号が割り当てられる。
2つめのjのループ処理における配列B(j)及び配列C(j)への参照により、配列B(j)及び配列C(j)のデータは、既にキャッシュライン上に配置されている配列A(j)のデータと競合する。このとき、配列A(j)のデータはキャッシュラインから追い出されるため、1つめのjのループ処理において、配列A(j)の先頭にアクセスするたびにキャッシュミスが発生する。
配列A(j)の先頭へのアクセスによりキャッシュミスが発生すると、jが1から16までのデータを含む1つめのキャッシュラインのデータが、キャッシュメモリに配置される。さらに、jが17のとき、2つめのキャッシュラインのデータへのアクセスにより、
2回目のキャッシュミスが発生する。これにより、ハードウェアプリフェッチが起動され、3つめ以降のキャッシュラインのデータがプリフェッチされる。しかしながら、jについてのループは17回で終了するため、3つめ以降のキャッシュラインのデータは活用されない。
このように、ループの回転数によっては、ハードウェアプリフェッチが起動されるまでの間に、連続領域へのアクセスが終了し、キャッシュミスの発生は低減されない。さらに、ハードウェアプリフェッチにより取得したデータは、プログラムでは使用されず、ハードウェアプリフェッチ自体が無駄となる。即ち、図6の例では、キャッシュラインの競合によるキャッシュスラッシングの発生に加えて、無駄なハードウェアプリフェッチが行われることになる。
<キャッシュブロッキング>
図7及び図8は、キャッシュブロッキングを説明するための図である。図7は、キャッシュブロッキング適用前後のソースコードの例を示す図である。キャッシュブロッキングは、ソフトウェアによる一般的な最適化手法であり、所定の間隔をあけてアクセスする領域に対し、「部分的に連続領域へのアクセス」となるようにアクセス方法を変更する。アクセス方法の変更により、アクセスしたデータをキャッシュメモリに残すことで、キャッシュミスが削減される。以下、キャッシュブロッキングは、ブロッキングとも称される。
具体的には、アクセスする領域がキャッシュメモリに収まるようにデータ構造をブロック化し、ブロックごとにアクセスすることで、キャッシュミスの発生が低減される。ループネスト構造の変更により、ブロック単位にアクセスするように、アクセス手法が変更される。キャッシュメモリに配置されたデータブロックが利用又は再利用されることで、メモリアクセス及びメモリ帯域幅への負担が軽減される。
図7のブロッキング適用前のソースコードの例では、最内ループ処理の制御変数が、配列B(j,k)の2次元目の変数kであるため、配列B(j,k)へのアクセスは、連続領域へのアクセスとはならず、キャッシュラインを超えたアクセスとなる。
図7のブロッキング適用後のソースコードの例では、各制御変数のループ処理が細分化される。これにより、アクセスする単位がブロック化され、配列B(j,k)のデータのうち、同一キャッシュラインに取得されたデータはキャッシュメモリに残る。
図8は、図7の配列Bによるメモリアクセスイメージの例を示す図である。図8のメモリアクセスイメージにおいて、メモリは横方向に配置される。ブロッキング適用前は、配列Bへのアクセスは、キャッシュラインを超えた縦方向のアクセスとなる。ブロッキング適用後は、配列Bへのアクセスは、ブロック化された領域へのアクセスとなる。ウェイ数が2の場合、同一キャッシュラインに割り当てられた2組のデータがキャッシュメモリに残るため、ブロッキング適用後の配列Bへのアクセスは、キャッシュヒットする。
しかし、キャッシュメモリ上の配列Bのデータは、他の変数へのアクセス等によりキャッシュから追い出される場合がある。この場合、キャッシュミスの発生は低減されず、ループ追加による分岐処理の増加により性能が劣化する。
また、ブロック長がキャッシュサイズよりも大きい場合、ブロッキングしたデータがキャッシュから溢れるため、キャッシュミスの発生は低減されない。さらに、キャッシュサイズの異なるシステムにプログラムを移行する場合には、ブロック長をキャッシュサイズ以下に修正しなければ、キャッシュミスの発生は低減されない。キャッシュミスの発生が低減されない場合、性能向上は図れない。
<第1実施形態>
第1実施形態では、コンパイラは、複数階層のループ処理において、所定の条件を満たす配列を特定し、特定した配列を多次元化する。配列の多次元化により、外側のループ処理の繰り返しごとに配列の先頭へのアクセスが繰り返されるのではなく、外側のループ処理全体を通じて、連続したアドレスを持つ領域がアクセスされる。これにより、ハードウェアプリフェッチは継続され、キャッシュミスの発生は低減される。
また、配列の多次元化により、外側のループ処理全体を通じて、連続したアドレスを持つ領域がアクセスされるため、配列のデータは別のキャッシュラインに割り当てられ、他の変数とのキャッシュラインの競合が回避される。これにより、キャッシュミスの発生は低減される。
図9から図11Bは、配列の多次元化により、キャッシュミスの発生が低減されることを説明するための図である。図9は、ハードウェアプリフェッチの継続に関する。図10Aから図11Bは、キャッシュラインの競合回避に関する。
図9は、配列の多次元化により、ハードウェアプリフェッチが継続される例を示す図である。図9のs3で示すソースコードには、iのループ処理が記載されている。iのループ処理は、jのループ処理を含む。jのループ処理は、配列A(j,i)を参照する処理を含む。配列A(j,i)は、外側のループ処理の制御変数iを追加次元の要素とする多次元配列として、配列A(j)を再定義したものである。
図9のソースコードは、Fortran言語で示されるが、C言語の場合、1次元配列A[j]は、2次元配列A[j,i]として再定義される。また、ここでは1次元配列が2次元配列に多次元化される例を示すが、次元に限定はなく、多次元化対象の配列は、2次元以上であってもよい。
図9のm1示すメモリアクセスイメージにおいて、配列Aの多次元化により、iが2からxまでの間、外側のループ処理でアクセスされる配列Aのデータが、連続領域として用意される。
配列Aのデータへの1回目のアクセスにより、星印で示されるキャッシュミスが発生する。配列Aのデータへの2回目のアクセスにより、連続領域に対する2回目のキャッシュミスが発生し、ハードウェアプリフェッチが起動される。外側のループ処理の間、連続領域のアクセスとなるため、配列Aのデータへの2回目以降のアクセスにおいてもハードウェアプリフェッチは継続される。
ハードウェアプリフェッチが継続されるため、配列Aのデータは、他の変数へのアクセスによってキャッシュメモリから追い出されても、プリフェッチにより再度キャッシュメモリに配置される。配列Aのデータがキャッシュメモリ上に残るため、キャッシュミスの発生は低減される。
図10Aから図11Bは、キャッシュラインの競合について説明するための図である。図10Aは、キャッシュラインの競合が生じるソースコードの例を示す図である。図10Aは、図6とほぼ同様のソースコードであるため、共通する部分についての説明は省略される。内側のループ処理のうち、1つめのjのループ処理は、配列A(j)を参照する処理を含み、jは1から33までの値をとる。
図10Bは、キャッシュラインの競合が生じた場合のメモリアクセスイメージの例を示
す図である。外側のループ処理においてiがnのとき、配列Aのデータへのアクセスにより、矢印で示されるキャッシュミスが2回発生する。
図10Bのf1で示す図において、横軸は配置アドレスを示し、縦軸はキャッシュライン番号Lを示す。キャッシュミスにより主記憶装置から取得される配列Aのデータは、下から2番目のキャッシュラインに配置される。次に、配置アドレスが、配列Aと所定の間隔で離れている配列Bが参照される。配列Bのデータは、配列Aと同じく下から2番目のキャッシュラインに配置される。次に、配置アドレスが、配列Bと所定の間隔で離れている配列Cが参照される。配列Cのデータも、配列Aと同じく下から2番目のキャッシュラインに配置されるが、ウェイ数が2の場合、配列A及び配列Bが2つのウェイを使用しているため、キャッシュラインの競合が発生する。キャッシュスラッシングにより、配列Aのデータは、キャッシュメモリから追い出される。
外側のループ処理において、iがn+1の場合の処理が実行される。配列Aのデータへのアクセスにおいて、配列Aのデータはキャッシュメモリから追い出されているため、矢印で示されるキャッシュミスが2回発生する。その後、iがnのときと同様に処理が進み、キャッシュラインの競合が発生する。キャッシュスラッシングにより、配列Aのデータがキャッシュメモリから追い出される。iがn+2以降の処理においても、同様に、キャッシュラインの競合が発生し、配列Aのデータにアクセスする毎に、キャッシュミスが発生する。
図11Aは、配列の多次元化により、キャッシュラインの競合を回避するソースコードの例を示す図である。図11Aは、図10Aとほぼ同様のソースコードであるため、共通する部分については説明を省略する。内側のループ処理のうち、1つめのjのループ処理は、配列A(j,i)を参照する処理を含む。配列A(j,i)は、配列A(j)を、外側のループ処理の制御変数iにより多次元化したものである。
図11Bは、キャッシュラインの競合が回避された場合のメモリアクセスイメージの例を示す図である。外側のループ処理においてiが1のとき、配列Aのデータへの1回目のアクセスにより、矢印で示されるキャッシュミスが2回発生する。
図11Bのf2で示す図において、横軸は配置アドレスを示し、縦軸はキャッシュライン番号Lを示す。キャッシュミスにより主記憶装置から取得される配列Aのデータは、下から2番目のキャッシュラインに配置される。次に、配置アドレスが、配列Aと所定の間隔で離れている配列Bが参照される。配列Bのデータは、下から2番目のキャッシュラインに配置される。次に、配置アドレスが、配列Bと所定の間隔で離れている配列Cが参照される。配列Cのデータは、下から2番目のキャッシュラインに配置される。
なお、配列Aの多次元化により、配列A(j,i)のデータを含む領域は、外側ループ処理の制御変数iについても連続領域となる。即ち、配列A(j,i)のデータは、異なるキャッシュライン番号を持つキャッシュラインにも配置される。このため、jのループ処理が繰り返されるごとに同じキャッシュラインがアクセスされるわけではなく、2回目以降のアクセスでは、異なるキャッシュライン番号のキャッシュラインがアクセスされる。
例えば、外側のループ処理においてiが2のとき、配列A(j,i)のデータへの2回目のアクセスは、下から3番目のキャッシュラインへのアクセスとなり、配列B及び配列Cとのキャッシュラインの競合は発生しない。iが3以降の場合も、配列B及び配列Cと同じキャッシュラインへのアクセスにはならず、配列B及び配列Cとのキャッシュラインの競合は発生しない。
即ち、配列の多次元化により、特定のキャッシュラインにアクセスが集中せず、他の変数のデータへのアクセスとのキャッシュラインの競合を減らすことができる。キャッシュラインの競合が減ることで、キャッシュミスの発生が低減される。
<装置構成>
図12は、情報処理装置1の装置構成の一例を示す図である。情報処理装置1は、プロセッサ101、主記憶装置102、補助記憶装置103、入力装置104、出力装置105、ネットワークインタフェース106、可搬記録媒体駆動装置107を備える。また、これらはバス109により互いに接続されている。
プロセッサ101は、例えば、Central Processing Unit(CPU)である。プロセッ
サ101は、補助記憶装置103又は可搬記録媒体110に保持されたOSや様々なアプリケーションプログラムを主記憶装置102にロードして実行することによって、様々な処理を実行する。プロセッサ101は、1つに限られず、複数備えられてもよい。
主記憶装置102は、プロセッサ101に、補助記憶装置103に格納されているプログラムをロードするための記憶領域、及びプログラムを実行するための作業領域を提供する。また、主記憶装置102は、データを保持するためのバッファとして用いられる。主記憶装置102は、例えば、Read Only Memory(ROM)、Random Access Memory(RAM)等の半導体メモリである。
補助記憶装置103は、様々なプログラムや、各プログラムの実行に際してプロセッサ101が使用するデータを格納する。補助記憶装置103は、例えば、Erasable Programmable ROM(EPROM)、又はハードディスクドライブ(Hard Disk Drive)等の不揮発性のメモリである。補助記憶装置103は、例えば、オペレーティングシステム(Operating System、OS)、コンパイラプログラム、その他様々なアプリケーションプログラムを保持する。
入力装置104は、例えば、キーボード、マウス等のポインティングデバイス等である。入力装置104から入力されたデータは、プロセッサ101に出力される。出力装置105は、プロセッサ101の処理の結果を出力する。出力装置105は、例えば、ディスプレイ、プリンタ、スピーカ等の音声出力装置である。
ネットワークインタフェース106は、ネットワークとの情報の入出力を行うインタフェースである。ネットワークインタフェース106は、有線のネットワークと接続するインタフェース、無線のネットワークと接続するインタフェースを含む。ネットワークインタフェース106は、例えば、Network Interface Card(NIC)、無線Local Area Network(LAN)カード等である。ネットワークインタフェース106で受信されたデータ等は、プロセッサ101に出力される。
可搬記録媒体駆動装置107は、可搬記録媒体110に記録されるプログラムや各種データを読出し、プロセッサ101に出力する。可搬記録媒体110は、例えば、SDカード、miniSDカード、microSDカード、Universal Serial Bus(USB)フラッシュメモリ、Compact Disc(CD)、Digital Versatile Disc(DVD)、フラッシュメモリカード等の記録媒体である。
例えば、情報処理装置1では、プロセッサ101が、補助記憶装置103に保持されるコンパイラプログラムを主記憶装置102にロードして実行する。なお、情報処理装置1の装置構成は一例であり、上記に限られず、実施の形態に応じて適宜構成要素の省略や置
換、追加が可能である。コンパイラプログラムは、例えば、可搬記録媒体110に記録されていてもよい。
<処理構成>
図13から図15Cは、情報処理装置1の処理構成を説明するための図である。図13は、情報処理装置の処理構成の一例を示す図である。情報処理装置1は、コンパイラ2、ソースプログラム11、機械語プログラム12、チューニング情報13を含む。
コンパイラ2は、Fortran等の高級言語で記述されたソースプログラム11を翻訳し、機械語プログラム12及びチューニング情報13を出力する。機械語プログラム12は、プロセッサ101が直接実行することができる一連の命令である。機械語プログラム12は、以下、オブジェクトとも称される。チューニング情報13は、コンパイラ2の翻訳結果に関する情報である。
コンパイラ2は、パーサー部20、中間コード変換部21、解析部22、最適化部23、コード生成部24を含む。プロセッサ101は、パーサー部20、中間コード変換部21、解析部22、最適化部23、コード生成部24として、主記憶装置102に実行可能に展開されたコンピュータプログラムを実行する。ただし、パーサー部20、中間コード変換部21、解析部22、最適化部23、コード生成部24のいずれか、またはその処理の一部がハードウェア回路により実行されてもよい。
パーサー部20は、ソースプログラム11を解析する。中間コード変換部21は、パーサー部20による解析結果に基づいて、ソースプログラム11を中間コードに変換する。解析部22は、中間コードを解析し、所定の条件を満たす配列を特定する。最適化部23は、解析部22が特定した配列を多次元化し、中間コードを最適化する。コード生成部24は、最適化部23により最適化された中間コードを機械語プログラム12に変換する。最適化部23及びコード生成部24は、生成部の一例である。
図14は、コンパイラにおける解析部22の処理構成の一例を示す図である。解析部22は、ループデータ記憶部30、配列データ記憶部31、ループ構造解析部32、配列解析部33、依存関係解析部34を含む。プロセッサ101は、ループデータ記憶部30、配列データ記憶部31、ループ構造解析部32、配列解析部33、依存関係解析部34として、主記憶装置102に実行可能に展開されたコンピュータプログラムを実行する。ただし、ループデータ記憶部30、配列データ記憶部31、ループ構造解析部32、配列解析部33、依存関係解析部34のいずれか、またはその処理の一部がハードウェア回路により実行されてもよい。
ループデータ記憶部30は、DO管理テーブル301を有する。DO管理テーブル301は、ループ構造解析部32、配列解析部33、依存関係解析部34によって作成される。DO管理テーブル301は、行番号、ネストレベル、制御変数、初期値、終値、増分、変数名等のループに関する情報を格納する。
配列データ記憶部31は、配列管理テーブル311を有する。配列管理テーブル311は、配列解析部33、依存関係解析部34によって作成される。配列管理テーブル311は、配列名、添字数、次元ごとの添字名、ループ内の定義及び参照等の配列に関する情報を格納する。
ループ構造解析部32は、中間コードにおいてループ構造を解析し、解析結果をDO管理テーブル301に格納する。配列解析部33は、中間コードにおいて配列構造を解析し、解析結果をDO管理テーブル301及び配列管理テーブル311に格納する。依存関係
解析部34は、中間コードにおいて配列に定義と参照の依存関係があるか否かを解析し、解析結果をDO管理テーブル301及び配列管理テーブル311に格納する。
解析部22は、ループ構造解析部32、配列解析部33、依存関係解析部34による解析結果から、多次元化対象の配列を特定することができる。解析部22は、配列管理テーブル311において、多次元化対象の配列であるか否かを示す属性を定義して、特定された配列が処理対象の配列である旨を記憶してもよい。
図15Aは、解析対象のループ処理のソースコードの例を示す図である。図15Aにおいて、DOで始まるkのループ処理が、100行目から記載されている。kのループ処理は、iのループ処理を含む。iのループ処理は、110行目から記載されている。iのループ処理は、jのループ処理を含む。jのループ処理は、120行目から記載されている。jのループ処理は、配列A(j,i)を定義する処理を含む。
図15Bは、配列管理テーブル311のデータ構造の一例を示す図である。配列管理テーブル311は、中間コードに含まれる配列ごとに、配列名、添字数、次元ごとの添字名、ループ内の定義及び参照等の属性の値を記憶する。
図15Bにおいて、配列管理テーブル311は、図15Aの配列A(j,i)に対応する属性の値を示す。「配列名」は、配列の変数名であり、“A”を示す。「添字数」は、j、i等の配列の添字の数であり、“2”を示す。次元ごとの添字名は、各次元の添字の変数名であり、「1次元」の添字名は“j”を示し、「2次元」の添字名は“i”を示す。ループ内の定義及び参照は、配列に対し、定義がされているか否か、又は参照がされているか否かを記憶する。図15Aの配列A(j,i)は、定義がされているが参照はされていない。このため、「定義」は“ON”を示し、「参照」は“OFF”を示す。
図15Cは、DO管理テーブル301のデータ構造の一例を示す図である。DO管理テーブル301は、中間コードに含まれるループ処理ごとに、行番号、ネストレベル、制御変数、初期値、終値、増分、変数名等の属性の値を記憶する。
図15Cにおいて、DO管理テーブル301は、図15Aのk、i、jについての3階層のループ処理における各階層でのループ処理の属性の値を示す。「行番号」は、ソースコード中の行番号であり、“100”を示す。「ネストレベル」は、当該ループ処理の階層である。「制御変数」は、当該ループ処理における繰返しを制御する変数である。「初期値」は、制御変数が採り得る値の初期値である。「終値」は、制御変数が採り得る値の終値である。「増分」は、ループ処理が先頭に戻るときの制御変数の増分である。「変数名」は、当該ループ処理内に含まれる配列の変数名である。「変数名」は、ループ処理に含まれる配列の変数名である。「次ネスト管理」は、1階層下のループ処理のレコードへの参照である。
図15Cのt1の表は、kのループ処理のレコードであり、kのループ処理の各属性の値を示す。「行番号」は“100”を示す。「ネストレベル」は“3”を示す。「制御変数」は“k”を示す。「初期値」は“1”を示す。「終値」は“z”を示す。「増分」は“1”を示す。図15Aのソースコードでは、kのループ処理は配列を含まないため、「変数名」は空欄である。「次ネスト管理」は、iのループ処理のレコードを指す。
図15Cのt2の表は、iのループ処理のレコードであり、iのループ処理の各属性の値を示す。「行番号」は“110”を示す。「ネストレベル」は“2”を示す。「制御変数」は“i”を示す。「初期値」は“1”を示す。「終値」は“x”を示す。「増分」は“1”を示す。図15Aのソースコードでは、iのループ処理は配列を含まないため、「
変数名」は空欄である。「次ネスト管理」は、jのループ処理のレコードを指す。
図15Cのt3の表は、jのループ処理のレコードであり、jのループ処理の各属性の値を示す。「行番号」は“120”を示す。「ネストレベル」は“1”を示す。「制御変数」は“j”を示す。「初期値」は“1”を示す。「終値」は“y”を示す。「増分」は“1”を示す。「変数名」は“A”を示す。
<配列の多次元化>
第1実施形態では、コンパイラ2は、ソースコードの解析により多次元化する配列を特定する。図16から図21は、配列の多次元化、及び多次元化対象の配列について説明するための図である。
図16は、コンパイラ2が特定した配列を多次元化するソースコードの例を示す図である。図16のs4で示すソースコードは、配列が多次元化される前のプログラムを示す。iのループ処理は、iが1からxまでの値をとり、回転数がxのループ処理である。iのループ処理は、jのループ処理を含む。jのループ処理は、jが1からyまでの値をとり、回転数がyのループ処理である。jのループ処理は、配列A(j)を参照する処理を含む。配列A(j)は、要素数100の整数型1次元配列である。
図16のs5で示すソースコードは、配列を多次元化した後のプログラムを示す。コンパイラ2は、配列A(j)を多次元化対象の配列として特定すると、配列A(j)を配列AA(j,i)に多次元化する。配列AA(j,i)は、100×nの整数型2次元配列である。なお、nは、外側のiのループ処理の回転数xと内側のjのループ処理の回転数yのいずれか大きいほうの値をとる。コンパイラ2は、多次元化前のプログラムを、多次元化後のプログラムとみなして翻訳する。
多次元化対象の配列は、翻訳時において要素数が定数である割付け配列、又は上下限が定数式で示される形状明示配列であると想定される。例えば、「INTEGER, DIMENTION(100)::A」のように要素数が定数100である配列が想定される。
また、多次元化対象の配列は、作業領域に割り当てられる局所的な配列、共通ブロック実体及び仮引数等である場合のほうが、初期値を持つグローバルな領域での変数等である場合よりも、多次元化による性能向上の効果が大きい。
さらに、多次元化対象の配列は、内側のループ処理で定義又は参照される配列であって、外側のループ処理で更新されない配列が想定される。なお、定義は、配列等の変数に何等かの値を代入する処理であり、例えば、「A(j)=・・・」のような式で例示される。一方、参照は、配列等の値を何等かの変数に代入する処理であり、例えば、「=・・・A(j)」のような式で例示される。
図16では、1次元配列を2次元配列に多次元化する例を示したが、多次元化対象の配列の次元数に限定はない。多次元化対象の配列の次元数は、2以上であってもよい。例えば、図17は、2次元配列を3次元配列に多次元化するソースコードの例を示す図である。
図17のs6で示すソースコードは、配列が多次元化される前のプログラムを示す。kのループ処理は、iのループ処理を含む。iのループ処理は、jのループ処理を含む。jのループ処理は、2次元配列AA(j,i)を参照する処理を含む。
図17のs7で示すソースコードは、配列を多次元化した後のプログラムを示す。コン
パイラ2は、配列AA(j,i)を多次元化対象の配列として特定すると、配列AA(j,i)を3次元配列AAA(j,i,k)に多次元化する。
図18Aから図19は、定義及び参照の依存関係の有無により、配列を多次元化の対象とするか否かを判断する例を説明するための図である。図18Aは、配列に、定義及び参照の依存関係がある場合の例を示す図である。図18Aのソースコードにおいて、iのループ処理は、iが1から3までの値をとり、jのループ処理を含む。jのループ処理は、jが1から5までの値をとり、配列A(j)にA(j)+1の値を代入する処理を含む。即ち、内側のjのループ処理において、配列A(j)に参照及び定義の依存関係が存在する。配列A(j)の各要素の初期値を0とすると、iが1のとき、配列A(j)の各要素の値は1となる。また、iが2のとき、配列A(j)の各要素の値は2となる。さらに、iが3のとき、配列A(j)の各要素の値は3となる。
図18Bは、図18Aの場合に、配列の多次元化を適用した例を示す図である。図18Bのソースコードは、図18Aのソースコードにおいて、配列A(j)を配列A(j,i)に多次元化したものである。配列A(j,i)の各要素の初期値を0とすると、各iに対して配列A(j,i)の各要素の値は1となり、図18Aの場合とは結果が異なる。
図18Aの場合は、外側ループの制御変数iの値が変わっても、同じ配列A(j)の領域が参照される。一方、図18Bの場合は、配列A(j)を配列A(j,i)に多次元化することにより、iの値ごとに領域が確保され、初期値が0に設定される。このため、図18Bでは、図18Aの場合と結果が異なる。したがって、定義及び参照の依存関係がある配列は、多次元化により結果が異なる場合があるため、多次元化の対象としない。
図19は、配列に、定義及び参照の依存関係がない場合の例を示す図である。図19のs8で示すソースコードは、図18Aと同じi及びjのループ処理を含む。jのループ処理は、配列A(j)にX(i)の値を代入する処理、即ち、配列A(j)を定義する処理を含む。配列A(j)の各要素の初期値を0とすると、iが1のとき、配列A(j)の各要素の値はX(1)となる。また、iが2のとき、配列A(j)の各要素の値はX(2)となる。さらに、iが3のとき、配列A(j)の各要素の値はX(3)となる。
図19のs9で示すソースコードは、図19のs8のソースコードにおいて、配列A(j)を配列A(j,i)に多次元化したものである。配列A(j,i)の各要素の初期値を0とすると、iが1のとき、配列A(j,1)の各要素の値はX(1)となる。また、iが2のとき、配列A(j,2)の各要素の値はX(2)となる。さらに、iが3のとき、配列A(j,3)の各要素の値はX(3)となる。即ち、配列を多次元化する前と同じ結果が得られる。したがって、定義及び参照の依存関係がない配列は、多次元化前と多次元化後で同じ結果が得られるため、多次元化の対象とする。
図20及び図21は、配列が、ループ構成が異なる複数のループ処理に含まれる否かにより、配列を多次元化の対象とするか否かを判断する例を説明する。図20は、同一の配列を含み構成が異なるループが複数存在するソースコードの例を示す図である。図20のd1で示すループ処理では、iのループ処理は、iが1から5の値をとり、jのループ処理を含む。jのループ処理は、jが1から5の値をとり、配列A(j)にX(i)を含む式を代入する処理を含む。一方、図20のd2で示すループ処理では、kのループ処理は、kが1から100の値をとり、jのループ処理を含む。jのループ処理は、jが1から7までの奇数の値をとり、配列A(j)にX(k)を含む式を代入する処理を含む。
d1とd2では、ループの回転数、増分、上位ループの制御変数名が一致しない。このように、ループの回転数、初期値、増分、終値、上位ループの制御変数名等のループ構成
が一致しない場合は、多次元化により結果が異なる場合があるため、多次元化の対象としない。
図21は、同一の配列を含み構成が同じループが複数存在するソースコードの例を示す図である。図21のd3で示すループ処理は、図20のd1で示すループ処理と同一であるため、その説明は省略する。図21のd4で示すループ処理では、lのループ処理は、lが1から10の値をとり、d3と同一のi及びjのループ処理を含む。jのループ処理は、配列A(j)にY(l)を含む式を代入する処理を含む。
d3とd4では、ループ処理全体の階層数及び配列A(j)に代入する値が異なるが、d4に含まれるiのループ処理は、d3のループ処理とループ構成が同じである。この場合、配列の多次元化前と多次元化後で同じ結果が得られるため、多次元化の対象とする。
<処理の流れ>
図22及び図23は、第1実施形態の処理の流れを説明するための図である。図22は、所定の配列を多次元化したオブジェクトを生成する処理のフローチャートの一例である。図22に示される処理は、例えば、コンパイラ2の起動により開始される。
OP1では、コンパイラ2は、解析部22により、多次元化対象の配列を特定する。なお、多次元化対象の配列を含むループ処理は、上位のループ処理に含まれる。また、多次元化対象の配列は、現ループ処理内で不変である。さらに、多次元化対象の配列は、ハードウェアプリフェッチの対象となる連続領域へアクセスする配列である。OP1の処理は、解析部22が、ソースプログラム11の解析により、ループ処理において、連続領域にアクセスする配列構造を特定する処理の一例である。次に処理がOP2に進む。
OP2では、コンパイラ2は、多次元化対象の配列について、ループ間で定義及び参照の依存関係があるか否かを判定する。依存関係がある場合には(OP2:Yes)、図22に示される処理が終了する。依存関係がない場合には(OP2:No)、処理がOP3に進む。
OP3では、コンパイラ2は、多次元化対象の配列を定義する領域を、上位ループの回転数に応じて多次元化された配列サイズ分確保する。例えば、配列A(j)を配列A(j,i)に多次元化した場合、コンパイラ2は、配列A(j)の領域を上位ループの回転数分拡張する。配列A(j)が静的領域の変数である場合、拡張される領域は、データ・スタックセクションに確保される。配列A(j)が動的領域の変数である場合、拡張される領域は、ヒープ領域等で動的に確保される。また、配列A(j)の初期値が定数の場合、コンパイラ2は、拡張した配列にも同じ初期値を設定する。次に処理がOP4に進む。
OP4では、コンパイラ2は、上位ループで不変な配列A(j)を上位ループの制御変数iに合わせて多次元化する。即ち、コンパイラ2は、配列A(j)を配列A(j,i)
に置き換える。次に処理がOP5に進む。
OP5では、コンパイラ2は、配列A(j)を配列A(j,i)に内部で置き換えて、オブジェクトを展開する。OP3からOP5の処理は、最適化部23及びコード生成部24が、配列構造が拡張された機械語プログラム12を、ソースプログラム11から生成する処理の一例である。オブジェクトが生成されることにより、図22に示される処理が終了する。
図23は、多次元化対象の配列を特定する処理のフローチャートの一例である。図23に示される処理は、図22のOP1の詳細な処理を示す。図23に示される処理は、例え
ば、コンパイラ2の起動後、解析部22に処理が進むことにより開始される。
OP11では、解析部22は、プログラム中の各ループ処理に対してDO管理テーブル301を作成する。次に処理がOP12に進む。OP12では、解析部22は、プログラム中の各配列に対して配列管理テーブル311を作成する。次に処理がOP13に進む。OP13では、解析部22は、処理対象の配列を取得する。次に処理がOP14に進む。
OP14では、解析部22は、配列管理テーブル311を検索し、処理対象の配列の「添字数」の値を取得する。また、解析部22は、DO管理テーブル301を検索し、処理対象の配列を含むループ処理の階層数、即ち、処理対象の配列を含むループ処理の最上位ループの「ネストレベル」の値を取得する。
解析部22は、添字数がループ処理の階層数より小さいか否かを判定する。添字数がループ処理の階層数より小さい場合には(OP14:Yes)、処理がOP15に進む。添字数がループ処理の階層数より小さくない場合には(OP14:No)、処理がOP19に進む。
OP15では、解析部22は、配列管理テーブル311を検索し、処理対象の配列の1次元目の添字、即ち、処理対象の配列の「1次元」の値を取得する。また、解析部22は、DO管理テーブル301を検索し、処理対象の配列を含む最内ループの「制御変数」の値を取得する。
解析部22は、1次元目の添字(以下、1次元添字ともいう)が最内ループの制御変数と等しいか否かを判定する。なお、1次元添字が最内ループの制御変数と等しくない場合でも、当該制御変数から伝播された変数であれば、1次元添字は、最内ループの制御変数と等しいとみなすことができる。1次元添字が最内ループの制御変数と等しい場合には(OP15:Yes)、処理がOP16に進む。1次元添字が最内ループの制御変数と等しくない場合には(OP15:No)、処理がOP19に進む。
OP16では、解析部22は、処理対象の配列へのアクセスが、ハードウェアプリフェッチの対象となる連続領域へのアクセスとなるか否かを調べる。ハードウェアプリフェッチはキャッシュライン単位で適用されるため、配列のデータを格納する領域のサイズが、キャッシュラインサイズより大きくなければ、配列へのアクセスは、ハードウェアプリフェッチの対象となる連続領域へのアクセスとならない。配列のデータを格納する領域のサイズは、例えば、1次元添字についての増分×配列要素数により求めることができる。
解析部22は、1次元添字の増分×配列要素数がキャッシュラインサイズより大きいか否かを判定する。1次元添字の増分×配列要素数がキャッシュラインサイズより大きい場合には(OP16:Yes)、処理がOP17に進む。1次元添字の増分×配列要素数がキャッシュラインサイズより大きくない場合には(OP16:No)、処理がOP19に進む。
OP17では、解析部22は、n次元添字(n>1)が、ネストレベルn以上のループ処理の制御変数と等しいか否かを調べる。具体的には、解析部22は、配列管理テーブル311を検索し、n次元添字を取得する。更に、解析部22は、DO管理テーブル301を検索し、「ネストレベル」がnのループの制御変数とn次元添字が等しいか否かを調べる。等しくない場合は、解析部22は、「ネストレベル」がn+1のループの制御変数とn次元添字が等しいか否かを調べる。等しくない場合は、解析部22は、更に外側のループの制御変数とn次元添字とを比較する処理を最外ループまで繰り返し、n次元添字(n>1)が、ネストレベルn以上のループ処理の制御変数と等しいか否かを判定する。
n次元添字がネストレベルn以上のループ処理の制御変数と等しい場合には(OP17:Yes)、処理がOP18に進む。n次元添字がネストレベルn以上のループ処理の制御変数と等しくない場合には(OP17:No)、処理がOP19に進む。
OP18では、解析部22は、処理対象の配列を多次元化対象の配列として特定する。特定された配列は、多次元化対象の配列リストとして、例えば、補助記憶装置103等に記憶してもよい。また、配列管理テーブル311において、多次元化対象の配列であるか否かを示す属性を定義して、処理対象の配列が多次元化対象の配列であるか否かを記憶してもよい。
OP19では、解析部22は、次の処理対象の配列があるか否かを判定する。次の処理対象の配列がある場合には(OP19:Yes)、処理がOP13に戻る。次の処理対象の配列がない場合には(OP19:No)、図23に示される処理が終了する。
図24は、多次元化対象の配列の具体例を示す図である。図23のソースコードには、Zのループ処理が記載されている。Zのループ処理は、Kのループ処理を含む。Kのループ処理は、Iのループ処理及び配列C(K)についての処理を含む。Iのループ処理は、Jのループ処理及び配列B(I)についての処理を含む。Jのループ処理は、配列A(J,I,K)、A(J,K,I)、A(J,K)、A(I,J,K)についての処理を含む。
図24のt4の表は、配列A(J,I,K)に対応する配列管理テーブル311のレコードを示す。「配列名」は“A”、「添字数」は“3”である、また、各次元の制御変数は、「1次元」では“J”、「2次元」では“I”、「3次元」では“K”である。
図23のOP14からOP17の処理を配列A(J,I,K)に適用すると、添字数は3、ループ処理の階層数は4であるため、OP14の条件を満たす。1次元の添字はJ、最内ループの制御変数もJであるため、OP15の条件を満たす。ここでは、配列A(J,I,K)は、OP16の条件を満たすものとする。2次元の添字Iは、ネストレベルが2であるループの制御変数Iと等しい。3次元の添え字Kは、ネストレベルが3であるループの制御変数Kと等しい。したがって、配列A(J,I,K)は、OP17の条件を満たし、多次元化対象の配列として特定される。配列A(J,I,K)は、配列A(J,I,K,Z)に多次元化される。
図23のOP14からOP17の処理を配列A(J,K,I)に適用すると、添字数は3、ループ処理の階層数は4であるため、OP14の条件を満たす。1次元の添字はJ、最内ループの制御変数もJであるため、OP15の条件を満たす。ここでは、配列A(J,K,I)は、OP16の条件を満たすものとする。2次元の添字Kは、ネストレベルが3であるループの制御変数Kと等しい。3次元の添え字Iは、ネストレベルが2であるループの制御変数Iと等しい。したがって、配列A(J,K,I)はOP17の条件を満たさず、多次元化の対象とならない。
同様に、図23のOP14からOP17の処理を配列A(J,K)及びA(I,J,K)に適用すると、配列A(J,K)は多次元化対象の配列であるが、配列A(I,J,K)は多次元化の対象とならない。
<第1実施形態の作用効果>
連続領域にアクセスする配列へのアクセスでは、外側のループごとに、先頭から同じ領域が繰り返しアクセスされる。即ち、ループネストの切り替えタイミングで、配列へのア
クセスは、同じ領域の先頭に戻る。このため、連続領域へのアクセスとならないため、ハードウェアプリフェッチは停止し、性能劣化が発生する。
第1実施形態では、コンパイラ2は、配列を多次元化し、外側のループごとに先頭から同じ領域をアクセスするのではなく、外側のループ処理を通じて連続領域へのアクセスとなるようにアクセス方法を変更する。これにより、ハードウェアプリフェッチは停止することなく継続的に起動されるため、持続的にキャッシュメモリにアクセスするデータは、事前に供給される。このため、データの取出しから参照までのアクセスコストは軽減され、性能向上が図られる。
また、コンパイラ2は、配列の多次元化により、特定のキャッシュラインへのアクセス集中を軽減し、他の変数へのアクセスとの間でキャッシュラインの競合を防ぐことができる。これにより、キャッシュミスの発生は低減され、性能向上が図られる。
なお、配列を多次元化することで、ループごとに配列要素のアドレスを算出する命令が展開されることになる。しかし、これらの命令による性能劣化よりも、ハードウェアプリフェッチが継続適用され、読出し遅延が隠蔽されることによる性能向上の効果のほうが大きい。
<第2実施形態>
第2実施形態では、コンパイラ2は、多次元化対象の配列を、プログラムの実行により得られるプロファイル情報に基づいて特定する。
連続領域にアクセスする配列と他の変数とがキャッシュライン競合しない場合、配列を再アクセスしたときには、キャッシュメモリ上に前回アクセスしたデータが残っている。このとき、ハードウェアプリフェッチによる効果は得られない。一方、配列を再アクセスするまでに、他の変数によりキャッシュライン上のデータが追い出されている場合には、ハードウェアプリフェッチによる効果が得られる。このように、再アクセス時までの他の変数の処理状況、キャッシュ状況等の実行時のプロファイル情報を活用することで、コンパイラ2は、多次元化対象の配列を適切に特定することができる。
第2実施形態における装置構成は、第1実施形態と同一である。図25は、第2実施形態における解析部22の処理構成の一例を示す図である。図25において、解析部22は、プロファイル情報10及びプロファイル情報解析部35を含む。第2実施形態における他の処理構成は、図13及び図14と同一である。第2実施形態では、第1実施形態と重複する説明は省略される。
プロファイル情報10は、コンパイラ2にプロファイル情報取得の翻訳オプションを指定してソースプログラム11を翻訳し、生成された機械語プログラム12を実行することにより出力される。生成された機械語プログラム12は、情報処理装置1で実行することができる。また、生成された機械語プログラム12は、他の情報処理装置で実行してもよい。このとき、プロファイル情報10は、例えば、可搬記録媒体110に記憶されてもよい。プロファイル情報解析部35は、可搬記録媒体110に記憶されたプロファイル情報10に基づいて、多次元化対象の配列を特定することができる。
プロファイル情報10は、例えば、配列が連続してアクセスする領域の長さ(以下、連続アクセス長ともいう)、配列へのアクセス回数を含む。また、プロファイル情報10は、配列と同一のキャッシュラインへの他の変数のアクセス回数、配列が連続してアクセスする領域におけるストライド幅等の情報も含む。
プロファイル情報解析部35は、プロファイル情報10を解析し、性能向上の効果を評価する。性能向上の効果は、所定の評価関数により算出される。プロファイル情報解析部35は、評価関数の値を所定の閾値と比較することで、多次元化対象の配列を特定する。
<配列の多次元化>
第2実施形態では、コンパイラ2は、プロファイル情報10に基づいて、多次元化する配列を特定する。図26から図29は、配列の多次元化、及び多次元化対象の配列について説明するための図である。
図26は、コンパイラ2がプロファイル情報10に基づいて特定した配列を多次元化するソースコードの例を示す図である。図26のs10で示すソースコードは、配列が多次元化される前のプログラムを示す。iのループ処理は、iが1からxまでの値をとり、回転数がxのループ処理である。iのループ処理は、jのループ処理を含む。jのループ処理は、jが1からyまでの値をとり、回転数がyのループ処理である。jのループ処理は、配列A(j)を参照する処理を含む。配列A(j)は、要素数100の整数型1次元配列である。s10のプログラムの実行により、プロファイル情報10が出力される。
図26のs11で示すソースコードは、プロファイル情報10に基づいて特定された配列を多次元化した後のプログラムを示す。コンパイラ2は、配列A(j)を多次元化対象の配列として特定すると、配列A(j)を配列AA(j,i)に多次元化する。配列AA(j,i)は、100×nの整数型2次元配列である。なお、nは、外側のiのループ処理の回転数xと内側のjのループ処理の回転数yのいずれか大きいほうの値をとる。コンパイラ2は、多次元化前のプログラムを、多次元化後のプログラムとみなして翻訳する。
図27Aから図29は、プロファイル情報10に基づいて、多次元化対象の配列を特定する具体例を説明するための図である。多次元化対象の配列は、例えば、キャッシュラインの競合密度及びキャッシュミスの回数を考慮して特定される。キャッシュラインの競合密度及びキャッシュミスの回数は、プロファイル情報10から算出又は取得することができる。
図27Aは、キャッシュラインの競合が生じる例を示す図である。図27Aにおいて、横軸は配置アドレスを示し、縦軸はキャッシュライン番号Lを示す。丸印で示されるデータは、下から2番目のキャッシュラインに配置される。次に、三角印で示されるデータが、下から2番目のキャッシュラインに配置される。さらに、四角印で示されるデータが、下から2番目のキャッシュラインに配置される。このとき、ウェイ数が2であるとすると、キャッシュラインの競合が生じ、丸印で示されるデータはキャッシュラインから追い出される。
図27Bは、キャッシュラインの競合が生じない例を示す図である。図27Bにおいて、縦軸及び横軸は、図27Aと同一である。また、丸印のデータ及び三角印のデータは、図27Aと同様に配置される。その後、下から2番目のキャッシュラインに配置されるデータはないため、ウェイ数が2であるとすると、キャッシュラインの競合は生じない。
キャッシュラインの競合密度は、多次元化対象の配列と他の変数が割り当てられるキャッシュラインが競合する頻度である。競合密度は、例えば、配列のデータにアクセスした後、再度アクセスするまでの間に、同一のキャッシュラインを少なくとも1回アクセスした他の変数の数とすることができる。他の変数によるアクセス回数は、プロファイル情報10から取得可能である。
図27Aのように、キャッシュラインの競合が生じる回数が増えるほど、競合密度は大
きくなる。図27Bのように、キャッシュラインの競合が生じなければ、競合密度は図27Aの場合よりも小さくなる。競合密度に比例して、性能向上の効果は増加する。
図28は、キャッシュミスが発生する例を示す図である。配列領域へのアクセス回数が増えるとともに、キャッシュミスが発生する割合は増加する。キャッシュミスが発生すると、コンパイラ2は、主記憶装置102から直接データを取り出す。
キャッシュミスの回数は、ハードウェアプリフェッチの停止により、主記憶装置102から直接データを取り出す回数である。配列の多次元化によってハードウェアプリフェッチは継続して起動されるため、ハードウェアプリフェッチが停止することで発生するキャッシュミスにより、主記憶装置102から直接データを取り出す回数が減少した場合に、性能向上の効果が期待される。即ち、キャッシュミスの回数に比例して、性能向上の効果は増加する。
また、キャッシュミスの回数は、連続アクセス長が長いほど減少するため、連続アクセス長に反比例する。さらに、キャッシュミスの回数は、配列へのアクセス回数が多いほど増えるため、配列へのアクセス回数に比例する。即ち、性能向上の効果は、連続アクセス長に反比例し、アクセス回数に比例する。
ここで、競合密度をR、キャッシュミスの回数をM、連続アクセス長をS、配列へのアクセス回数をLとすると、性能向上の効果Eは、以下の式で表すことができる。
E=R×M
=R×1/S×L
競合密度Rは、配列のデータにアクセスした後、再度アクセスするまでの間に、同一のキャッシュラインを少なくとも1回アクセスした他の変数の数とする。連続アクセス長S及び配列へのアクセス回数Lは、プロファイル情報から取得される。
図29は、性能向上の効果を評価するための属性のデータ構造の一例を示す図である。コンパイラ2は、これらの属性データをプロファイル情報10から取得し、例えば、補助記憶装置103等に記憶してもよい。図29では、多次元化対象の配列ごとに、アクセス回数(L)、連続アクセス長(S)、キャッシュ競合密度(R)の属性値が記憶される。図29において、配列“array1”のアクセス回数(L)は“1000”、連続アクセス長(S)は“80”、キャッシュ競合密度(R)は“10”である。また、配列“array2”のアクセス回数(L)は“2000”、連続アクセス長(S)は“40”、キャッシュ競合密度(R)は“20”である。
コンパイラ2は、多次元化対象の配列の属性データを用いて、性能向上の効果を、以下の評価関数により算出することができる。
評価関数 =Σ(L(i)*l(i)+1/S(i)*s(i)+R(i)*r(i))
l(i)、s(i)、r(i)は、各属性に対する重み係数であり、配列ごとに任意の値が設定される。コンパイラ2は、配列の多次元化を適用する前の評価関数の値を閾値とし、適用後の値と比較する。コンパイラ2は、評価関数の値が閾値以上となる配列の組合せを多次元化対象とすることができる。また、コンパイラ2は、多次元化対象の配列の組合せをプロファイル情報に基づいて変更し、性能向上の効果が増加する配列の組合せを特定することができる。
なお、上記評価関数は一例であり、限定はない。また、評価関数に用いる属性は、アクセス回数(L)、連続アクセス長(S)、キャッシュ競合密度(R)に限られず、適宜追
加し、組み合わせてもよい。さらに閾値は、プロセッサ101が取得した実測値(経験値)又は論理値でもよく、限定はない。
<処理の流れ>
図30及び図31は、プロファイル情報10に基づいて配列を多次元化する処理を説明するための図である。図30は、プロファイル情報を取得する処理のフローチャートの一例である。図30に示される処理は、例えば、プロファイル情報10の取得を指示する翻訳オプションが指定されて、コンパイラ2が起動されることにより開始される。
OP21では、コンパイラ2は、プロファイル情報取得の翻訳オプションの指定により、対象プログラムを翻訳する。次に処理がOP22に進む。OP22では、コンパイラ2は、プログラム実行により、プロファイル情報を出力する。プロファイル情報は、例えば、多次元化対象の配列のアクセス回数、連続アクセス長、キャッシュ競合密度、ストライド幅等を含む。多次元化対象の配列は、例えば、連続領域にアクセスする配列で、外側ループごとに同じ領域の先頭からのアクセスを繰り返す配列である。
図31は、プロファイル情報に基づいて配列を多次元化する処理のフローチャートの一例である。図31に示される処理は、例えば、コンパイラ2が起動されることにより開始される。
OP31では、コンパイラ2は、多次元化対象の配列に対して、実行時のプロファイル情報を取得する。次に処理がOP32に進む。OP32では、コンパイラ2は、プロファイル情報のアクセス回数、連続アクセス長、キャッシュ競合密度、ストライド幅等の情報に基づいて、多次元化対象の配列を特定する。次に処理がOP33に進む。OP33では、コンパイラ2は、多次元化対象の配列に対する命令を展開し、処理が終了する。
<第2実施形態の作用効果>
第2実施形態では、コンパイラ2は、多次元化対象の配列を、プログラムの実行により得られるプロファイル情報に基づいて特定する。これにより、コンパイラ2は、配列が再アクセスされるまでの他の変数の処理状況、キャッシュメモリの使用状況等に応じて、性能向上の効果が期待できる配列を多次元化対象として特定し、性能向上を図ることができる。
また、コンパイラ2は、配列のアクセス回数、連続アクセス長、キャッシュ競合密度等の属性値を用いた評価関数により、性能向上の効果を算出し、より効果が期待できる配列の組合せを、多次元化対象として特定し、性能向上を図ることができる。
<第3実施形態>
第3実施形態では、コンパイラ2は、ユーザが指定した配列を多次元化の対象とすることができる。ユーザは、コンパイラ2により出力されたチューニング情報13に基づいて、多次元化対象の配列を選択することができる。ユーザは、コンパイラ2に対し、ソースコード中に翻訳指示行を追加することにより多次元化対象の配列を指定することができる。また、ユーザは、コンパイラ2に対し、オプションにより多次元化対象の配列を指定することがきる。
第3実施形態における装置構成は、第1実施形態と同一である。第3実施形態における他の処理構成は、第2実施形態と同一である。第2実施形態では、第1実施形態及び第2実施形態と重複する説明は省略される。
<配列の多次元化>
第3実施形態では、ユーザは、コンパイラ2に対し、ソースコード中に翻訳指示行を追加することにより多次元化対象の配列を指定することができる。
図32は、ユーザが翻訳指示行により指定した配列を多次元化するソースコードの例を示す図である。図32のs12で示すソースコードは、配列が多次元化される前のプログラムを示す。iのループ処理は、iが1からxまでの値をとり、回転数がxのループ処理である。iのループ処理は、jのループ処理を含む。jのループ処理は、jが1からyまでの値をとり、回転数がyのループ処理である。jのループ処理は、翻訳指示行“!ocl array_expansion(A(100,n))”を含む。この翻訳指示行は
、配列A(j)を、100×nの整数型2次元配列に多次元化することを指定する。また、jのループ処理は、配列A(j)を参照する処理を含む。配列A(j)は、要素数100の整数型1次元配列である。
図32のs13で示すソースコードは、配列を多次元化した後のプログラムを示す。コンパイラ2は、配列A(j)を多次元化対象の配列として特定すると、配列A(j)を100×nの整数型2次元配列のAA(j,i)に多次元化する。コンパイラ2は、多次元化前のプログラムを、多次元化後のプログラムとみなして翻訳する。
図32では、1次元配列A(j)を2次元配列AA(j,i)に多次元化する例を示したが、コンパイラ2は、2次元以上の配列も同様に多次元化できる。例えば、配列A(i,j,k,…)は、配列AA(A(i,j,k,…),n)に置き換えられる。
なお、翻訳指示行の“!ocl”は、FORTRANソースコード中に、ユーザが任意に指定することができるコンパイラへの指示であり、OCL指定と称される。C言語においてOCL指定に相当する構文は、「#pragma」で始まる文字列である。
また、ユーザは、OCL指定をソースコード中に指定しなくても、コンパイラ2に対し、所定の翻訳オプション(例えば、−Karray_expansion)を指定することにより、OCL指定と同等の機械語プログラムを出力させることができる。ここではFORTRANを例として説明するが、使用する言語は、C言語などの他のプログラム言語であってもよい。また、翻訳オプションのキーワード、OCL等の制御指示名などは任意であり、上記に限定するものではない。
<処理の流れ>
図33は、コンパイラが、翻訳指示行により指定された配列を展開する処理のフローチャートの一例である。図33に示される処理は、例えば、コンパイラ2の起動により開始される。
OP41では、コンパイラ2は、プログラム中にocl等の翻訳指示行で指定された多次元化対象の配列を特定する。次に処理がOP42に進む。OP42では、コンパイラ2は、多次元化対象の配列について、現ループと上位ループ間で、定義及び参照の依存関係があるか否かを判定する。依存関係がある場合には(OP42:Yes)、図33に示される処理が終了する。依存関係がない場合には(OP42:No)、処理がOP43に進む。
OP43では、コンパイラ2は、対象配列を指定された次元の配列に置き換えて、オブジェクトを展開する。例えば、配列A(j)がAA(j,i)に置き換えられる。次に処理が終了する。
<第3実施形態の作用効果>
第3実施形態では、コンパイラ2は、ユーザが指定した配列を多次元化の対象とすることができる。これにより、多次元化の要素数及び次元数等も任意に指定することができ、多次元化対象の配列を柔軟に変更することができる。
<変形例>
多次元化対象の配列は、第1実施形態から第3実施形態による方法を適宜組み合わせて特定してもよい。これにより、コンパイラ2による自動抽出では対応できない場合でも、ユーザが個別に指定することで、多次元化対象の配列を柔軟に特定することができる。
また、各実施形態は、連続領域へのアクセスを検知してハードウェアプリフェッチを開始する情報処理装置1において、配列を多次元化する例を説明する。これに対し、一定間隔のストライド幅が開いた領域へのアクセスを検知してハードウェアプリフェッチを開始する情報処理装置1においても、各実施形態による配列の多次元化は適用可能である。配列の多次元化により、一定間隔のストライド幅が開いた領域へのアクセスに対しても、ハードウェアプリフェッチは継続して起動される。
<記録媒体>
コンピュータその他の機械、装置(以下、コンピュータ等)に上記いずれかの機能を実現させるプログラムをコンピュータ等が読み取り可能な記録媒体に記録することができる。そして、コンピュータ等に、この記録媒体のプログラムを読み込ませて実行させることにより、その機能を提供させることができる。
ここで、コンピュータ等が読み取り可能な記録媒体とは、データやプログラム等の情報を電気的、磁気的、光学的、機械的、または化学的作用によって蓄積し、コンピュータ等から読み取ることができる記録媒体をいう。このような記録媒体のうちコンピュータ等から取り外し可能なものとしては、例えばフレキシブルディスク、光磁気ディスク、CD−ROM、CD−R/W、DVD、ブルーレイディスク、DAT、8mmテープ、フラッシュメモリなどのメモリカード等がある。また、コンピュータ等に固定された記録媒体としてハードディスクやROM(リードオンリーメモリ)等がある。さらに、Solid State Drive(SSD)はコンピュータ等から取り外し可能な記録媒体としても、コンピュータ等
に固定された記録媒体としても利用可能である。
<その他>
上述した実施形態は、以下の付記を開示する。以下の付記は適宜組み合わせることが可能である。
(付記1)
情報処理装置が有する解析部に、前記情報処理装置が主記憶装置上の連続する領域へのアクセスを検知してハードウェアプリフェッチを開始し、前記連続する領域へのアクセス終了を検知してハードウェアプリフェッチを停止する場合に、ソースプログラムの解析により、ループ処理において、ハードウェアプリフェッチの対象となる配列構造を特定させ、
前記情報処理装置が有する生成部に、前記配列構造への第1のアクセスの次に生じる第2のアクセスが、前記第1のアクセスで参照される領域と連続する領域を参照するように前記配列構造を変更させた機械語プログラムを、前記ソースプログラムから生成させる、ための情報処理プログラム。
(付記2)
前記解析部に、
前記機械語プログラムの実行により取得される、プログラムの性能に関するプロファイ
ル情報に基づいて前記配列構造を特定させる、
付記1に記載の情報処理プログラム。
(付記3)
前記プロファイル情報は、前記配列構造へのアクセス回数、前記配列構造を記憶する領域の長さ、及び前記配列構造を記憶するキャッシュメモリ上の領域への他の変数からのアクセス状況の少なくとも1つを含む、
付記2に記載の情報処理プログラム。
(付記4)
前記解析部に、
前記ソースプログラム中の命令による指示に基づいて、又は、前記機械語プログラム実行時のオプションによる指示に基づいて、前記配列構造を特定させることができる、
付記1から3のいずれか一項に記載の情報処理プログラム。
(付記5)
前記解析部に、前記情報処理装置が前記主記憶装置上の一定間隔のストライド幅が開いた領域へのアクセスを検知してハードウェアプリフェッチを開始し、前記一定間隔のストライド幅が開いた領域へのアクセス終了を検知してハードウェアプリフェッチを停止する場合に、前記ソースプログラムの解析により、ループ処理において、ハードウェアプリフェッチの対象となる配列構造を特定させる、
付記1から4のいずれか一項に記載の情報処理プログラム。
(付記6)
主記憶装置上の連続する領域へのアクセスを検知してハードウェアプリフェッチを開始し、前記連続する領域へのアクセス終了を検知してハードウェアプリフェッチを停止する情報処理装置において、
ソースプログラムの解析により、ループ処理において、ハードウェアプリフェッチの対象となる配列構造を特定する解析部と、
前記配列構造への第1のアクセスの次に生じる第2のアクセスが、前記第1のアクセスで参照される領域と連続する領域を参照するように前記配列構造を変更した機械語プログラムを、前記ソースプログラムから生成する生成部と、
を備える情報処理装置。
(付記7)
前記解析部は、
前記機械語プログラムの実行により取得される、プログラムの性能に関するプロファイル情報に基づいて前記配列構造を特定する、
付記6に記載の情報処理装置。
(付記8)
前記プロファイル情報は、前記配列構造へのアクセス回数、前記配列構造を記憶する領域の長さ、及び前記配列構造を記憶するキャッシュメモリ上の領域への他の変数からのアクセス状況の少なくとも1つを含む、
付記7に記載の情報処理装置。
(付記9)
前記解析部は、
前記ソースプログラム中の命令による指示に基づいて、又は、前記機械語プログラム実行時のオプションによる指示に基づいて、前記配列構造を特定することができる、
付記6から8のいずれか一項に記載の情報処理装置。
(付記10)
前記解析部は、前記情報処理装置が前記主記憶装置上の一定間隔のストライド幅が開いた領域へのアクセスを検知してハードウェアプリフェッチを開始し、前記一定間隔のストライド幅が開いた領域へのアクセス終了を検知してハードウェアプリフェッチを停止する場合に、前記ソースプログラムの解析により、ループ処理において、ハードウェアプリフェッチの対象となる配列構造を特定する、
付記6から9のいずれか一項に記載の情報処理装置。
(付記11)
情報処理装置が有する解析部が、前記情報処理装置が主記憶装置上の連続する領域へのアクセスを検知してハードウェアプリフェッチを開始し、前記連続する領域へのアクセス終了を検知してハードウェアプリフェッチを停止する場合に、ソースプログラムの解析により、ループ処理において、ハードウェアプリフェッチの対象となる配列構造を特定し、
前記情報処理装置が有する生成部が、前記配列構造への第1のアクセスの次に生じる第2のアクセスが、前記第1のアクセスで参照される領域と連続する領域を参照するように前記配列構造を変更した機械語プログラムを、前記ソースプログラムから生成する、
情報処理方法。
(付記12)
前記解析部は、
前記機械語プログラムの実行により取得される、プログラムの性能に関するプロファイル情報に基づいて前記配列構造を特定する、
付記11に記載の情報処理方法。
(付記13)
前記プロファイル情報は、前記配列構造へのアクセス回数、前記配列構造を記憶する領域の長さ、及び前記配列構造を記憶するキャッシュメモリ上の領域への他の変数からのアクセス状況の少なくとも1つを含む、
付記12に記載の情報処理方法。
(付記14)
前記解析部は、
前記ソースプログラム中の命令による指示に基づいて、又は、前記機械語プログラム実行時のオプションによる指示に基づいて、前記配列構造を特定することができる、
付記11から13のいずれか一項に記載の情報処理方法。
(付記15)
前記解析部は、前記情報処理装置が前記主記憶装置上の一定間隔のストライド幅が開いた領域へのアクセスを検知してハードウェアプリフェッチを開始し、前記一定間隔のストライド幅が開いた領域へのアクセス終了を検知してハードウェアプリフェッチを停止する場合に、前記ソースプログラムの解析により、ループ処理において、ハードウェアプリフェッチの対象となる配列構造を特定する、
付記11から14のいずれか一項に記載の情報処理方法。