以下、本実施の形態を図面を参照して説明する。
[第1の実施の形態]
第1の実施の形態を説明する。
図1は、第1の実施の形態の並列計算装置を示す図である。
第1の実施の形態の並列計算装置10は、複数のプロセッサ(プロセッサコアと呼ばれるものを含む)と共有メモリとを有する共有メモリ型マルチプロセッサ装置である。並列計算装置10は、複数のプロセッサを用いて複数のスレッドを並列に実行することができる。これら複数のスレッドは共有メモリを使用することができる。並列計算装置10は、ユーザが操作するクライアントコンピュータでもよいし、クライアントコンピュータからアクセスされるサーバコンピュータでもよい。
並列計算装置10は、記憶部11および演算部12を有する。記憶部11は、RAM(Random Access Memory)などの揮発性の半導体メモリでもよいし、HDD(Hard Disk Drive)やフラッシュメモリなどの不揮発性のストレージでもよい。記憶部11は、上記の共有メモリであってもよい。演算部12は、例えば、CPU(Central Processing Unit)、CPUコア、DSP(Digital Signal Processor)などのプロセッサである。演算部12は、上記の複数のスレッドの1つを実行するプロセッサであってもよい。演算部12は、例えば、記憶部11などのメモリに記憶されたプログラムを実行する。実行されるプログラムには、並列処理プログラムが含まれる。
記憶部11は、コード13を記憶する。コード13は、例えば、並列計算装置10のプロセッサが実行できるようにコンパイルされたオブジェクトコードである。コード13は、ループ13aを含む。ループ13aは、配列13b(配列A)の中のインデックス13c(第1のインデックス)が示す要素を更新する更新処理を含む。また、ループ13aは、配列13bの中のインデックス13d(第2のインデックス)が示す要素を参照する参照処理を含む。インデックス13c,13dは「添字」と呼ばれることがある。
インデックス13c,13dは、ループ13aの繰り返しを制御するループ変数に依存する。例えば、インデックス13c,13dはそれぞれループ変数nを含む。また、インデックス13c,13dの少なくとも一方は、実行時に値の決まるパラメータに依存する。パラメータは、「変数」や「引数」などと呼ばれてもよい。パラメータは、例えば、ループの実行前までに値が決まりループ内では値が不変な変数である。パラメータは、ループ変数の上限値、下限値、増分など、ループ変数の値域を定義するものであってもよい。また、パラメータは、インデックス13c,13dの少なくとも一方に含まれていてもよい。図1の例では、インデックス13cはパラメータp1を含み、インデックス13dはパラメータp2を含んでいる。パラメータp1,p2の値は実行時に決まるため、インデックス13c,13dの値域を静的に算出することは難しい。
演算部12は、記憶部11に記憶されたコード13の実行を開始する。演算部12は、ループ13aが実行される直前に、ループ13aが並列化可能か判定する検査処理を行う。並列化可能と判定された場合、並列計算装置10は、複数のプロセッサ(演算部12を含んでもよい)を用いてループ13aの繰り返し処理を並列に実行してもよい。一方、並列化不可と判定された場合、演算部12は、ループ13aが並列化不可であることを示す警告15を出力する。演算部12は、例えば、警告15を示すメッセージを記憶部11または他の記憶装置にログとして記憶する。また、演算部12は、例えば、警告15を示すメッセージを、並列計算装置10に接続されたディスプレイに表示する。
検査処理では、演算部12は、実行時におけるパラメータの値に基づいて、範囲14a(第1の範囲)および範囲14b(第2の範囲)を算出する。範囲14aは、配列13bに含まれる複数の要素のうち、ループ13aの繰り返し全体を通じて(ループ13aの開始から終了までの間に)更新される要素の範囲である。範囲14bは、配列13bに含まれる複数の要素のうち、ループ13aの繰り返し全体を通じて参照される要素の範囲である。範囲14a,14bは、配列13bに割り当てられたメモリ上の記憶領域を示すアドレス(メモリアドレス)を用いて表現されてもよい。
例えば、演算部12は、ループ変数の下限値・上限値・増分(繰り返し処理1回毎に増加するループ変数の値)、配列13bの要素1つ当たりのデータサイズ、その他のパラメータの値などに基づいて、範囲14a,14bを算出する。範囲14a,14bの少なくとも一方は、配列13bに含まれる複数の要素のうちの連続した要素の集合を示すものであってもよく、メモリ上の連続した記憶領域を示すものであってもよい。また、範囲14a,14bの少なくとも一方は、配列13bに含まれる複数の要素のうちの規則的に離れた要素の集合を示すものであってもよく、メモリ上の規則的に離れた記憶領域を示すものであってもよい。複数の要素または複数の記憶領域が規則的に離れているとは、それら要素または記憶領域が所定の間隔を空けて離れている場合を含む。
そして、演算部12は、算出した範囲14aと範囲14bとを比較する。範囲14aと範囲14bとが部分的に重複している場合(一部の要素が重複し一部の要素が重複していない場合)、演算部12は、ループ13aが並列化不可であると判定する。すると、演算部12は、並列化不可であることを示す警告15を出力する。一方、範囲14aと範囲14bとが一致している場合、演算部12は、ループ13aが並列化可能であると判定してもよい。また、範囲14aと範囲14bとが重複していない場合(重複する要素が存在しない場合)、演算部12は、ループ13aが並列化可能であると判定してもよい。
なお、演算部12が実行する上記の検査処理は、ライブラリプログラムとして実装されてもよい。その場合、コンパイラによって、コード13のループ13aの直前に、当該ライブラリプログラムを呼び出す呼び出し命令が挿入されていてもよい。
第1の実施の形態の並列計算装置10によれば、ループ13aが実行される前に、実行時におけるパラメータの値に基づいて、配列13bの中の更新される要素の範囲14aと参照される要素の範囲14bとが算出される。そして、ループ13aが実行される前に、範囲14aと範囲14bとが比較され、範囲14aと範囲14bとが部分的に重複する場合にはループ13aが並列化不可であることを示す警告15が出力される。
このように、実行時に値の決まるパラメータが存在する場合であっても、ループ13aの実行前にループ13aが並列化可能か判定できる。並列化可能と判定された場合には、複数のスレッドを起動してループ13aの繰り返し処理を並列に実行することが可能となる。一方、ループ13a内でインデックス13c,13dの値を検査するようにすると、この検査のためにループ13aを並列化することが難しくなる。よって、第1の実施の形態によれば、ループ13aの並列化が阻害されなくなり、ループ13aの実行時間を短縮することができる。また、多重ループによってインデックス13cの値とインデックス13dの値の具体的な組み合わせを全て算出する方法と比べて、検査処理の負荷を軽減することができる。その結果、ループ13aの並列化に関するコード13の誤りを効率的に検出することができ、コード13の実行効率が向上する。
[第2の実施の形態]
次に、第2の実施の形態を説明する。
図2は、第2の実施の形態のコンパイル装置を示す図である。
第2の実施の形態のコンパイル装置20は、第1の実施の形態の並列計算装置10のような並列処理能力を有するコンピュータに実行させるコードを生成する。コンパイル装置20は、ソフトウェアとして実装されたコンパイラを実行するこのピュータでもよい。コンパイル装置20は、ユーザが操作するクライアントコンピュータでもよいし、クライアントコンピュータからアクセスされるサーバコンピュータでもよい。
コンパイル装置20は、記憶部21および変換部22を有する。記憶部21は、RAMなどの揮発性の半導体メモリでもよいし、HDDやフラッシュメモリなどの不揮発性のストレージでもよい。変換部22は、例えば、CPUやDSPなどのプロセッサである。変換部22は、例えば、記憶部21などのメモリに記憶されたプログラムを実行する。実行されるプログラムには、コンパイルプログラムが含まれる。
記憶部21は、コード23(第1のコード)を記憶する。コード23は、ユーザが作成したソースコードでもよいし、ソースコードから変換された中間コードでもよいし、ソースコードまたは中間コードから変換されたオブジェクトコードでもよい。また、記憶部21は、コード23から変換されるコード24(第2のコード)を記憶する。コード24は、ソースコードでもよいし中間コードでもよいしオブジェクトコードでもよい。なお、コード23,24は、「プログラム」や「命令の集合」などと呼ぶことも可能である。
コード23は、ループ23aを含む。ループ23aは、配列23bの中のインデックス23c(第1のインデックス)が示す要素を更新する更新処理を含む。また、ループ23aは、配列23bの中のインデックス23d(第2のインデックス)が示す要素を参照する参照処理を含む。インデックス23c,23dの少なくとも一方は、実行時に値の決まるパラメータに依存する。ループ23aは、第1の実施の形態のループ13aに対応する。配列23bは、第1の実施の形態の配列13bに対応する。インデックス23c,23dは、第1の実施の形態のインデックス13c,13dに対応する。
コード24は、ループ23aが並列化可能か否か検査する機能を有する。コード24は、「デバッグ用のコード」と言うこともできる。コンパイル装置20は、ユーザから入力されたコンパイルコマンドに所定のオプション(例えば、デバッグオプション)が付加されている場合のみ、コード23をコード24に変換するようにしてもよい。
変換部22は、コード23からループ23aを検出する。検出するループ23aは、ユーザによって並列化が指示されたループであってもよい。変換部22は、ループ23aから配列23bの更新の命令と配列23bの参照の命令を抽出する。インデックス23c,23dの少なくとも一方がパラメータに依存するため、ループ23aの繰り返し全体を通じて(ループ23aの開始から終了までの間に)同じ要素が更新されかつ参照されるかを静的に判定することが難しい。そこで、変換部22は、ループ23aの直前に検査処理24aが実行されるようにコード23からコード24を生成する。例えば、変換部22は、ループ23aの直前に検査用の命令を挿入する。また、例えば、変換部22は、ループ23aの直前に、検査用のライブラリを呼び出す呼び出し命令を挿入する。
検査処理24aは、実行時におけるパラメータの値に基づいて、配列23bの中の更新される要素の範囲24b(第1の範囲)と配列23bの中の参照される要素の範囲24c(第2の範囲)とを算出することを含む。範囲24b,24cは、第1の実施の形態の範囲14a,14bに対応する。また、検査処理24aは、範囲24bと範囲24cとを比較し、両者が部分的に重複する場合にループ23aが並列化不可であることを示す警告25を出力することを含む。警告25は、第1の実施の形態の警告15に対応する。
第2の実施の形態のコンパイル装置20によれば、コード23からループ23aが検出され、ループ23aの実行前にループ23aが並列化可能か検査する検査処理24aが実行されるように、コード23がコード24に変換される。検査処理24aでは、実行時のパラメータの値に基づいて、更新される範囲24bと参照される範囲24cとが算出され、範囲24b,24cが部分的に重複する場合に警告25が出力される。
これにより、コンパイル時にループ23aの並列化可否を静的に判定することが難しい場合であっても、実行時にループ23aの並列化可否を動的に判定するコード24を生成することができる。また、並列化可能と判定された場合には、ループ23aの繰り返し処理を並列に実行することが可能となる。よって、ループ23aの並列化が阻害されなくなり、ループ23aの実行時間を短縮することができる。また、ループ23aの実行前に検査処理24aが実行されるため、検査の負荷を軽減することができる。その結果、ループ23aの並列化に関するコード23の誤りを効率的に検出できるようになる。
[第3の実施の形態]
次に、第3の実施の形態を説明する。
図3は、第3の実施の形態の情報処理システムを示す図である。
第3の実施の形態の情報処理システムは、並列計算装置100およびコンパイル装置200を有する。並列計算装置100とコンパイル装置200とは、ネットワーク30を介して接続されている。並列計算装置100およびコンパイル装置200はそれぞれ、ユーザが操作するクライアントコンピュータでもよいし、ネットワーク30を介してクライアントコンピュータからアクセスされるサーバコンピュータでもよい。なお、並列計算装置100は、第1の実施の形態の並列計算装置10に対応する。コンパイル装置200は、第2の実施の形態のコンパイル装置20に対応する。
並列計算装置100は、複数のCPUコアを用いて複数のスレッドを並列に実行することができる共有メモリ型マルチプロセッサ装置である。コンパイル装置200は、ユーザが作成したソースコードを、並列計算装置100が実行可能なオブジェクトコードに変換する。その際、コンパイル装置200は、ソースコードから、並列に動作する複数のスレッドを起動可能な並列処理用のオブジェクトコードを生成することができる。生成されたオブジェクトコードは、コンパイル装置200から並列計算装置100に送信される。ただし、第3の実施の形態ではプログラムをコンパイルする装置と実行する装置とを別装置としたが、両者が同一装置であってもよい。
図4は、並列計算装置のハードウェア例を示すブロック図である。
並列計算装置100は、CPU101、RAM102、HDD103、画像信号処理部104、入力信号処理部105、媒体リーダ106および通信インタフェース107を有する。上記ユニットはバス108に接続される。
CPU101は、プログラムの命令を実行するプロセッサである。CPU101は、HDD103に記憶されたプログラムやデータの少なくとも一部をRAM102にロードし、プログラムを実行する。CPU101は、CPUコア101a〜101dを有する。CPUコア101a〜101dは、並列にスレッドを実行することができる。ただし、CPU101が有するCPUコアの数は、2以上の任意の数でよい。なお、CPU101a〜101dそれぞれを「プロセッサ」と呼ぶこともあるし、CPU101a〜101dの集合またはCPU101を「プロセッサ」と呼ぶこともある。
RAM102は、CPU101が実行するプログラムやCPU101が演算に用いるデータを一時的に記憶する揮発性の半導体メモリである。なお、並列計算装置100は、RAM以外の種類のメモリを備えてもよく、複数個のメモリを備えてもよい。
HDD103は、OS(Operating System)やミドルウェアやアプリケーションソフトウェアなどのソフトウェアのプログラム、および、データを記憶する不揮発性の記憶装置である。プログラムには、コンパイル装置200によってコンパイルされたものが含まれる。なお、並列計算装置100は、フラッシュメモリやSSD(Solid State Drive)などの他の種類の記憶装置を備えてもよく、複数の不揮発性の記憶装置を備えてもよい。
画像信号処理部104は、CPU101からの命令に従って、並列計算装置100に接続されたディスプレイ111に画像を出力する。ディスプレイ111としては、CRT(Cathode Ray Tube)ディスプレイ、液晶ディスプレイ(LCD:Liquid Crystal Display)、プラズマディスプレイ(PDP:Plasma Display Panel)、有機EL(OEL:Organic Electro-Luminescence)ディスプレイなどを用いることができる。
入力信号処理部105は、並列計算装置100に接続された入力デバイス112から入力信号を取得し、CPU101に出力する。入力デバイス112としては、マウスやタッチパネルやタッチパッドやトラックボールなどのポインティングデバイス、キーボード、リモートコントローラ、ボタンスイッチなどを用いることができる。また、並列計算装置100に、複数の種類の入力デバイスが接続されていてもよい。
媒体リーダ106は、記録媒体113に記録されたプログラムやデータを読み取る読み取り装置である。記録媒体113として、例えば、フレキシブルディスク(FD:Flexible Disk)やHDDなどの磁気ディスク、CD(Compact Disc)やDVD(Digital Versatile Disc)などの光ディスク、光磁気ディスク(MO:Magneto-Optical disk)、半導体メモリなどを使用できる。媒体リーダ106は、例えば、記録媒体113から読み取ったプログラムやデータをRAM102またはHDD103に格納する。
通信インタフェース107は、ネットワーク30に接続され、ネットワーク30を介してコンパイル装置200などの他の装置と通信を行うインタフェースである。通信インタフェース107は、スイッチなどの通信装置とケーブルで接続される有線通信インタフェースでもよいし、基地局と無線リンクで接続される無線通信インタフェースでもよい。
なお、並列計算装置100は、媒体リーダ106を備えていなくてもよく、ユーザが操作する端末装置から制御可能である場合には画像信号処理部104や入力信号処理部105を備えていなくてもよい。また、ディスプレイ111や入力デバイス112が、並列計算装置100の筐体と一体に形成されてもよい。CPU101は、第1の実施の形態の演算部12に対応する。RAM102は、第1の実施の形態の記憶部11に対応する。
図5は、コンパイル装置のハードウェア例を示すブロック図である。
コンパイル装置200は、CPU201、RAM202、HDD203、画像信号処理部204、入力信号処理部205、媒体リーダ206および通信インタフェース207を有する。上記ユニットはバス208に接続される。
CPU201は、並列計算装置100のCPU101と同様の機能を有する。ただし、CPU201が有するCPUコアの数は1つであってもよく、CPU201はマルチプロセッサでなくてもよい。RAM202は、並列計算装置100のRAM102と同様の機能を有する。HDD203は、並列計算装置100のHDD103と同様の機能を有する。ただし、HDD203が記憶するプログラムには、コンパイルプログラムが含まれる。
画像信号処理部204は、並列計算装置100の画像信号処理部104と同様の機能を有する。画像信号処理部204は、コンパイル装置200に接続されたディスプレイ211に画像を出力する。入力信号処理部205は、並列計算装置100の入力信号処理部105と同様の機能を有する。入力信号処理部205は、コンパイル装置200に接続された入力デバイス212から入力信号を取得する。
媒体リーダ206は、並列計算装置100の媒体リーダ106と同様の機能を有する。媒体リーダ206は、記録媒体213に記録されたプログラムやデータを読み取る。ただし、記録媒体113と記録媒体213とが同一媒体であってもよい。通信インタフェース207は、並列計算装置100の通信インタフェース107と同様の機能を有する。通信インタフェース207は、ネットワーク30に接続されている。
なお、コンパイル装置200は、媒体リーダ206を備えていなくてもよく、ユーザが操作する端末装置から制御可能である場合には画像信号処理部204や入力信号処理部205を備えていなくてもよい。また、ディスプレイ211や入力デバイス212が、コンパイル装置200の筐体と一体に形成されてもよい。CPU201は、第2の実施の形態の変換部22に対応する。RAM102は、第2の実施の形態の記憶部21に対応する。
次に、ループの並列化の可否について説明する。
ユーザが作成するソースコードには、複数のスレッドを用いてループの繰り返し処理を並列実行することを示す並列化指示文が記載されていることがある。第3の実施の形態では主に、プログラミング言語の仕様の中に並列化指示文が規定されている場合を考える。ソースコードに並列化指示文が記載されていると、コンパイル装置200は、原則としてユーザの指示に従い、ループの繰り返し処理を並列実行するオブジェクトコードを生成する。すなわち、繰り返し処理のうちのi回目の処理とj回目の処理(i,jは異なる正の整数)が、異なるCPUコア上で動作する異なるスレッドによって実行される。
ただし、ループ内で、配列に値を格納すること(「定義」)と当該配列から値を取得すること(「参照」)の両方が行われる場合、i回目の処理とj回目の処理との間に依存関係が生じることがある。依存関係は、i回目の処理で定義される配列の要素と、j回目の処理で参照される配列の要素とが同一である場合に発生する。繰り返し処理に依存関係のあるループを並列化すると、実行順序が保証されないために処理結果が不定になってしまう。このため、繰り返し処理に依存関係のあるループに対して並列化指示文が記載されたソースコードは、意味的な誤りのあるソースコードであると言うことができる。
繰り返し処理に依存関係があるか否かは、定義に使用されるインデックス(配列の添字)の値域と参照に使用されるインデックスの値域との間の関係による。ループの繰り返しを制御するループ変数の下限値・上限値・増分が定数であり、2つのインデックスが共にループ変数のみに依存する場合、コンパイル装置200は、コンパイル時に静的に2つのインデックスの値域を特定することができる。この場合、コンパイル装置200は、コンパイル時に静的にループの並列化可否を判定することが可能である。
配列を格納するメモリ領域のうち、ループの繰り返し処理全体を通じて定義される領域(定義領域)と、ループの繰り返し処理全体を通じて参照される領域(参照領域)とが比較される。定義領域と参照領域とが完全一致する場合、i回目の処理内で定義と参照の間に依存関係が生じる可能性はあるものの、i回目の処理とj回目の処理との間に依存関係が生じる可能性は低い。このため、完全一致の場合は並列化可能と判定できる。また、定義領域と参照領域とが重複しない場合、並列化可能と判定できる。一方、定義領域と参照領域とが一部重複する場合、ある領域がi回目の処理において定義されj回目の処理において参照される可能性が高い。このため、一部重複の場合は並列化不可と判定できる。
このように、配列の定義に使用するインデックスと参照に使用するインデックスとがループ変数以外の変数に依存しない場合、ループの並列化可否をコンパイル時に静的に判定できる。これに対し、配列の定義に使用するインデックスと参照に使用するインデックスとがループ変数以外の変数に依存する場合、ループの並列化可否をコンパイル時に静的に判定することは難しい。ループ変数以外の変数は、ループ変数の下限値、上限値または増分を示すことがある。また、ループ変数以外の変数は、インデックスに含まれることがある。ループ変数以外の変数は、通常、ループの実行前に値が決定されてループ内では不変である。この場合、コンパイル装置200は、ループの並列化可否を実行時に動的に判定するデバッグ用のオブジェクトコードを生成する。デバッグ用のオブジェクトコードは、コンパイルコマンドにデバッグオプションが付加された場合のみ生成される。
以下、定義領域と参照領域とを比較する例を説明する。
図6は、ソースコード例を示す第1の図である。
ソースコード41には、サブルーチンfoo1が記載されている。サブルーチンfoo1は、引数としてk1,k2,inを取得する。サブルーチンfoo1は、長さがk2+1の実数型の配列aを定義する。サブルーチンfoo1は、ループ変数nの値をk1からk2まで1ずつ増加させながらループを実行する。このループは、並列化指示文「CONCURRENT」によって並列に実行するよう指示されている。ループは、配列aのn+in番目の要素の定義と、配列aのn番目の要素の参照とを含む。配列aの定義領域および参照領域は、実行時に値が決まる引数k1,k2,inに依存することになる。ソースコード41には、引数としてk1=1,k2=1000,in=1を指定してサブルーチンfoo1を呼び出す呼び出し文が記載されている。
ソースコード42には、サブルーチンfoo2が記載されている。サブルーチンfoo2は、引数としてk1,k2,k3,k4を取得する。サブルーチンfoo2は、ループ変数nの値をk1からk2まで1ずつ増加させながらループを実行する。ループは、配列aのn+k3番目の要素の定義と、配列aのn+k4番目の要素の参照とを含む。配列aの定義領域および参照領域は、実行時に値が決まる引数k1,k2,k3,k4に依存することになる。ソースコード42には、引数としてk1=1,k2=1000,k3=0,k4=0を指定してサブルーチンfoo2を呼び出す呼び出し文が記載されている。
ソースコード43には、サブルーチンfoo3が記載されている。サブルーチンfoo3は、引数としてk1,k2を取得する。サブルーチンfoo3は、ループ変数nの値をk1からk2まで1ずつ増加させながらループを実行する。ループは、配列aのn+1000番目の要素の定義と、配列aのn番目の要素の参照とを含む。配列aの定義領域および参照領域は、実行時に値が決まる引数k1,k2に依存することになる。ソースコード43には、引数としてk1=1,k2=1000を指定してサブルーチンfoo3を呼び出す呼び出し文が記載されている。
図7は、定義領域と参照領域の関係例を示す第1の図である。
定義領域61aは、ソースコード41のループに基づいて定義される領域である。具体的には、定義領域61aは、a(2)からa(1001)までの連続した領域である。参照領域61bは、ソースコード41のループに基づいて参照される領域である。具体的には、参照領域61bは、a(1)からa(1000)までの連続した領域である。定義領域61aと参照領域61bとを比較すると、a(2)からa(1000)までが重複している一方、a(1)とa(1001)は重複していない。すなわち、定義領域61aと参照領域61bとは一部重複している。このため、ソースコード41のループは並列化不可であり、ソースコード41は意味的な誤りを有している。
定義領域62aは、ソースコード42のループに基づいて定義される領域である。具体的には、定義領域62aは、a(1)からa(1000)までの連続した領域である。参照領域62bは、ソースコード42のループに基づいて参照される領域である。具体的には、参照領域62bは、a(1)からa(1000)までの連続した領域である。定義領域62aと参照領域62bとを比較すると、両者は完全一致している。このため、ソースコード42のループは並列化可能であり、ソースコード42に意味的な誤りはない。
定義領域63aは、ソースコード43のループに基づいて定義される領域である。具体的には、定義領域63aは、a(1001)からa(2000)までの連続した領域である。参照領域63bは、ソースコード43のループに基づいて参照される領域である。具体的には、参照領域63bは、a(1)からa(1000)までの連続した領域である。定義領域63aと参照領域63bとを比較すると、両者は重複しない。このため、ソースコード43のループは並列化可能であり、ソースコード43に意味的な誤りはない。
ここで、定義領域61aと参照領域61bは、引数k1,k2,inから算出できる。このため、並列計算装置100は、ループの実行前に、定義領域61aと参照領域61bを算出して並列化不可であることを判定できる。同様に、定義領域62aと参照領域62bは、引数k1,k2,k3,k4から算出できる。このため、並列計算装置100は、ループの実行前に、定義領域62aと参照領域62bを算出して並列化可能であることを判定できる。また、定義領域63aと参照領域63bは、引数k1,k2から算出できる。このため、並列計算装置100は、ループの実行前に、定義領域63aと参照領域63bを算出して並列化可能であることを判定できる。このように、定義領域と参照領域が連続領域である場合、ループの実行前に並列化可否を判定できる。
図8は、ソースコード例を示す第2の図である。
ソースコード44には、サブルーチンfoo4が記載されている。サブルーチンfoo4は、引数としてkを取得する。サブルーチンfoo4は、大きさが1000×1000の実数型の二次元配列aを定義する。サブルーチンfoo4は、ループ変数nの値を1から999まで1ずつ増加させながらループを実行する。ループは、二次元配列aの(1,n)〜(1000,n)の範囲の要素の定義を含む。また、ループは、二次元配列aの(1,n+1)〜(1000,n+1)の範囲の要素の参照を含む。ただし、参照される要素はk個に1個の割合で選択される。二次元配列aの参照領域は、実行時に値が決まる引数kに依存することになる。ソースコード44には、引数としてk=2を指定してサブルーチンfoo4を呼び出す呼び出し文が記載されている。
ソースコード45には、サブルーチンfoo5が記載されている。サブルーチンfoo5は、引数としてkを取得する。サブルーチンfoo5は、ループ変数nの値を1から1000まで1ずつ増加させながらループを実行する。ループは、二次元配列aの(1,n)〜(1000,n)の範囲の要素の定義を含む。また、ループは、二次元配列aの(1,n)〜(1000,n)の範囲の要素の参照を含む。ただし、参照される要素はk個に1個の割合で選択される。二次元配列aの参照領域は、実行時に値が決まる引数kに依存することになる。ソースコード45には、引数としてk=1を指定してサブルーチンfoo5を呼び出す呼び出し文が記載されている。
ソースコード46には、サブルーチンfoo6が記載されている。サブルーチンfoo6は、引数としてk1,k2を取得する。サブルーチンfoo6は、ループ変数nの値をk1+1からk2−1まで1ずつ増加させながらループを実行する。ループは、二次元配列aの(n,1)の要素の定義と、二次元配列aの(1,n)の要素の参照とを含む。二次元配列aの定義領域および参照領域は、実行時に値が決まる引数k1,k2に依存することになる。ソースコード46には、引数としてk1=1,k2=1000を指定してサブルーチンfoo6を呼び出す呼び出し文が記載されている。
図9は、定義領域と参照領域の関係例を示す第2の図である。
二次元配列の要素については、メモリ上に(1,1),(2,1),…,(1000,1),(1,2),(2,2),…,(1000,2),…のような順序で配置されるものとする。すなわち、二次元目のインデックスの値が同じで一次元目のインデックスの値が異なる要素が、連続したメモリ領域に配置されるものとする。
定義領域64aは、ソースコード44のループに基づいて定義される領域である。具体的には、定義領域64aは、a(1,1)からa(1000,999)までの連続した領域である。参照領域64bは、ソースコード44のループに基づいて参照される領域である。具体的には、参照領域64bは、a(1,2),a(3,2),…,a(999,999),…,a(999,1000)のように規則的に間隔の空いた領域である。定義領域64aと参照領域64bとを比較すると、参照領域64bのa(1,2),…,a(999,999)が定義領域64aと重複している。一方、参照領域64bのa(1,1000),…,a(999,1000)は定義領域64aと重複していない。すなわち、定義領域64aと参照領域64bとは一部重複している。このため、ソースコード44のループは並列化不可であり、ソースコード44は意味的な誤りを有している。
定義領域65aは、ソースコード45のループに基づいて定義される領域である。具体的には、定義領域65aは、a(1,1)からa(1000,1000)までの連続した領域である。参照領域65bは、ソースコード45のループに基づいて参照される領域である。具体的には、参照領域65bは、a(1,1)からa(1000,1000)までの連続した領域である。引数kの値が1であるため、参照領域64bとは異なり、参照領域65bは実質的に、間隔の空いた領域ではなく連続した領域になっている。定義領域65aと参照領域65bとを比較すると、両者は完全一致している。このため、ソースコード45のループは並列化可能であり、ソースコード45に意味的な誤りはない。
定義領域66aは、ソースコード46のループに基づいて定義される領域である。具体的には、定義領域66aは、a(2,1)からa(999,1)までの連続した領域である。参照領域66bは、ソースコード46のループに基づいて参照される領域である。具体的には、参照領域66bは、a(1,2),a(1,3),…,a(1,999)のように規則的に間隔の空いた領域である。定義領域66aと参照領域66bとを比較すると、両者は重複しない。このため、ソースコード46のループは並列化可能であり、ソースコード46に意味的な誤りはない。
ここで、定義領域64aは静的に算出でき、参照領域64bは引数kから算出できる。このため、並列計算装置100は、ループの実行前に、定義領域64aと参照領域64bを算出して並列化不可であることを判定できる。同様に、定義領域65aは静的に算出でき、参照領域65bは引数kから算出できる。このため、並列計算装置100は、ループの実行前に、定義領域65aと参照領域65bを算出して並列化可能であることを判定できる。また、定義領域66aと参照領域66bは、引数k1,k2から算出できる。このため、並列計算装置100は、ループの実行前に、定義領域66aと参照領域66bを算出して並列化可能であることを判定できる。このように、定義領域が連続領域であり参照領域が規則的領域である場合、ループの実行前に並列化可否を判定できる。
なお、参照領域65bは連続した領域になっているものの、コンパイル時には引数kの値が不明であるため、ソースコード45からは参照領域65bが規則的領域になると仮定してオブジェクトコードが生成される。
図10は、ソースコード例を示す第3の図である。
ソースコード47には、サブルーチンfoo7が記載されている。サブルーチンfoo7は、引数としてkを取得する。サブルーチンfoo7は、大きさが1000×1000の実数型の二次元配列aを定義する。サブルーチンfoo7は、ループ変数nの値を1から999まで1ずつ増加させながらループを実行する。ループは、二次元配列aの(1,n+1)〜(1000,n+1)の範囲の要素の定義を含む。ただし、定義される要素はk個に1個の割合で選択される。また、ループは、二次元配列aの(1,n)〜(1000,n)の範囲の要素の参照を含む。二次元配列aの定義領域は、実行時に値が決まる引数kに依存することになる。ソースコード47には、引数としてk=2を指定してサブルーチンfoo7を呼び出す呼び出し文が記載されている。
ソースコード48には、サブルーチンfoo8が記載されている。サブルーチンfoo8は、引数としてkを取得する。サブルーチンfoo8は、ループ変数nの値を1から1000まで1ずつ増加させながらループを実行する。ループは、二次元配列aの(1,n)〜(1000,n)の範囲の要素の定義を含む。ただし、定義される要素はk個に1個の割合で選択される。また、ループは、二次元配列aの(1,n)〜(1000,n)の範囲の要素の参照を含む。二次元配列aの定義領域は、実行時に値が決まる引数kに依存することになる。ソースコード48には、引数としてk=1を指定してサブルーチンfoo8を呼び出す呼び出し文が記載されている。
ソースコード49には、サブルーチンfoo9が記載されている。サブルーチンfoo9は、引数としてk1,k2を取得する。サブルーチンfoo9は、ループ変数nの値をk1+1からk2−1まで1ずつ増加させながらループを実行する。ループは、二次元配列aの(1,n)の要素の定義と、二次元配列aの(n,1)の要素の参照とを含む。二次元配列aの定義領域および参照領域は、実行時に値が決まる引数k1,k2に依存することになる。ソースコード49には、引数としてk1=1,k2=1000を指定してサブルーチンfoo9を呼び出す呼び出し文が記載されている。
図11は、定義領域と参照領域の関係例を示す第3の図である。
定義領域67aは、ソースコード47のループに基づいて定義される領域である。具体的には、定義領域67aは、a(1,2),a(3,2),…,a(999,999),…,a(999,1000)のように規則的に間隔の空いた領域である。参照領域67bは、ソースコード47のループに基づいて参照される領域である。具体的には、参照領域67bは、a(1,1)からa(1000,999)までの連続した領域である。定義領域67aと参照領域67bとを比較すると、定義領域67aのa(1,2),…,a(999,999)が参照領域67bと重複している。一方、定義領域67aのa(1,1000),…,a(999,1000)は参照領域67bと重複していない。すなわち、定義領域67aと参照領域67bとは一部重複している。このため、ソースコード47のループは並列化不可であり、ソースコード47は意味的な誤りを有している。
定義領域68aは、ソースコード48のループに基づいて定義される領域である。具体的には、定義領域68aは、a(1,1)からa(1000,1000)までの連続した領域である。参照領域68bは、ソースコード48のループに基づいて参照される領域である。具体的には、参照領域68bは、a(1,1)からa(1000,1000)までの連続した領域である。引数kの値が1であるため、定義領域67aとは異なり、定義領域68aは実質的に、間隔の空いた領域ではなく連続した領域になっている。定義領域68aと参照領域68bとを比較すると、両者は完全一致している。このため、ソースコード48のループは並列化可能であり、ソースコード48に意味的な誤りはない。
定義領域69aは、ソースコード49のループに基づいて定義される領域である。具体的には、定義領域69aは、a(1,2),a(1,3),…,a(1,999)のように規則的に間隔の空いた領域である。参照領域69bは、ソースコード49のループに基づいて参照される領域である。参照領域69bは、a(2,1)からa(999,1)までの連続した領域である。定義領域69aと参照領域69bとを比較すると、両者は重複しない。このため、ソースコード49のループは並列化可能であり、ソースコード49に意味的な誤りはない。
ここで、定義領域67aは引数kから算出でき、参照領域67bは静的に算出できる。このため、並列計算装置100は、ループの実行前に、定義領域67aと参照領域67bを算出して並列化不可であることを判定できる。同様に、定義領域68aは引数kから算出でき、参照領域68bは引数kから算出できる。このため、並列計算装置100は、ループの実行前に、定義領域68aと参照領域68bを算出して並列化可能であることを判定できる。また、定義領域69aと参照領域69bは、引数k1,k2から算出できる。このため、並列計算装置100は、ループの実行前に、定義領域69aと参照領域69bを算出して並列化可能であることを判定できる。このように、定義領域が規則的領域であり参照領域が連続領域である場合、ループの実行前に並列化可否を判定できる。
なお、定義領域68aは連続した領域になっているものの、コンパイル時には引数kの値が不明であるため、ソースコード48からは定義領域68aが規則的領域になると仮定してオブジェクトコードが生成される。
図12は、ソースコード例を示す第4の図である。
ソースコード51には、サブルーチンfoo11が記載されている。サブルーチンfoo11は、引数としてk1,k2,inを取得する。サブルーチンfoo11は、ループ変数nの値をk1からk2まで2ずつ増加させながらループを実行する。ループは、配列aのn+in+1番目の要素の定義と、配列aのn番目の要素の参照とを含む。配列aの定義領域および参照領域は、実行時に値が決まる引数k1,k2,inに依存することになる。ソースコード51には、引数としてk1=1,k2=1000,in=1を指定してサブルーチンfoo11を呼び出す呼び出し文が記載されている。
ソースコード52には、サブルーチンfoo12が記載されている。サブルーチンfoo12は、引数としてk1,k2,k3,k4を取得する。サブルーチンfoo12は、ループ変数nの値をk1からk2まで2ずつ増加させながらループを実行する。ループは、配列aのn+k3番目の要素の定義と、配列aのn+k4番目の要素の参照とを含む。定義領域および参照領域は、実行時に値が決まる引数k1,k2,k3,k4に依存することになる。ソースコード52には、引数としてk1=1,k2=1000,k3=0,k4=0を指定してサブルーチンfoo12を呼び出す呼び出し文が記載されている。
図13は、ソースコード例を示す第5の図である。
ソースコード53には、サブルーチンfoo13が記載されている。サブルーチンfoo13は、引数としてk1,k2を取得する。サブルーチンfoo13は、ループ変数nの値をk1からk2まで2ずつ増加させながらループを実行する。ループは、配列aのn番目の要素の定義と、配列aのn+1000番目の要素の参照とを含む。配列aの定義領域および参照領域は、実行時に値が決まる引数k1,k2に依存することになる。ソースコード53には、引数としてk1=1,k2=1000を指定してサブルーチンfoo13を呼び出す呼び出し文が記載されている。
ソースコード54には、サブルーチンfoo14が記載されている。サブルーチンfoo14は、引数としてk1,k2,inを取得する。サブルーチンfoo14は、ループ変数nの値をk1からk2まで2ずつ増加させながらループを実行する。ループは、配列aのn+in番目の要素の定義と、配列aのn番目の要素の参照とを含む。配列aの定義領域および参照領域は、実行時に値が決まる引数k1,k2,inに依存することになる。ソースコード54には、引数としてk1=1,k2=1000,in=1を指定してサブルーチンfoo14を呼び出す呼び出し文が記載されている。
図14は、定義領域と参照領域の関係例を示す第4の図である。
定義領域71aは、ソースコード51のループに基づいて定義される領域である。具体的には、定義領域71aは、a(3),a(5),…,a(999),a(1001)のように規則的に間隔の空いた領域である。参照領域71bは、ソースコード51のループに基づいて参照される領域である。具体的には、参照領域71bは、a(1),a(3),a(5),…,a(999)のように規則的に間隔の空いた領域である。定義領域71aと参照領域71bとを比較すると、a(3),a(5),…,a(999)が重複している一方、a(1)とa(1001)は重複していない。すなわち、定義領域71aと参照領域71bとは一部重複している。このため、ソースコード51のループは並列化不可であり、ソースコード51は意味的な誤りを有している。
定義領域72aは、ソースコード52のループに基づいて定義される領域である。具体的には、定義領域72aは、a(1),a(3),…,a(999)のように規則的に間隔の空いた領域である。参照領域72bは、ソースコード52のループに基づいて参照される領域である。具体的には、参照領域72bは、a(1),a(3),…,a(999)のように規則的に間隔の空いた領域である。定義領域72aと参照領域72bとを比較すると、両者は完全一致している。このため、ソースコード52のループは並列化可能であり、ソースコード52に意味的な誤りはない。
図15は、定義領域と参照領域の関係例を示す第5の図である。
定義領域73aは、ソースコード53のループに基づいて定義される領域である。具体的には、定義領域73aは、a(1001),a(1003),…,a(1999)のように規則的に間隔の空いた領域である。参照領域73bは、ソースコード53のループに基づいて参照される領域である。具体的には、参照領域73bは、a(1),a(3),…,a(999)のように規則的に間隔の空いた領域である。定義領域73aと参照領域73bとを比較すると、両者は重複しない。このため、ソースコード53のループは並列化可能であり、ソースコード53に意味的な誤りはない。
定義領域74aは、ソースコード54のループに基づいて定義される領域である。具体的には、定義領域74aは、a(2),a(4),a(6),…,a(1000)のように規則的に間隔の空いた領域である。参照領域74bは、ソースコード54のループに基づいて参照される領域である。具体的には、参照領域74bは、a(1),a(3),a(5),…,a(999)のように規則的に間隔の空いた領域である。定義領域74aと参照領域74bとを比較すると、定義領域74aは偶数番目の要素のみ含むのに対して参照領域74bは奇数番目の要素のみ含むため両者は重複しない。このため、ソースコード54のループは並列化可能であり、ソースコード54に意味的な誤りはない。
ここで、定義領域71aと参照領域71bは、引数k1,k2,inから算出できる。このため、並列計算装置100は、ループの実行前に、定義領域71aと参照領域71bを算出して並列化不可であることを判定できる。同様に、定義領域72aと参照領域72bは、引数k1,k2,k3,k4から算出できる。このため、並列計算装置100は、ループの実行前に、定義領域72aと参照領域72bを算出して並列化可能であることを判定できる。定義領域73aと参照領域73bは、引数k1,k2から算出できる。このため、並列計算装置100は、ループの実行前に、定義領域73aと参照領域73bを算出して並列化可能であることを判定できる。定義領域74aと参照領域74bは、引数k1,k2,inから算出できる。このため、並列計算装置100は、ループの実行前に、定義領域74aと参照領域74bを算出して並列化可能であることを判定できる。定義領域と参照領域が規則的領域である場合、ループの実行前に並列化可否を判定できる。
後述するように、コンパイル装置200は、ループ内に配列の定義を検出すると、ソースコードの記載から、その定義領域が連続領域になるか規則的領域になるかそれ以外の領域(非規則的領域)になるか判定することができる。また、コンパイル装置200は、ループ内に配列の参照を検出すると、ソースコードの記載から、その参照領域が連続領域になるか規則的領域になるか非規則的領域になるか判定することができる。
上記のように、連続的な定義領域または規則的な定義領域と、連続的な参照領域または規則的な参照領域とは、ループの実行前に比較することが可能である。一方、定義領域と参照領域の少なくとも一方が非規則的になる場合、定義領域と参照領域とをループの実行前に比較することは難しい。この場合、ループ内で並列化可否が判定されることになる。ただし、定義領域および参照領域は、連続的かまたは規則的であることが多い。このため、ループ外で検査処理を行う場合が多く、ループ内で検査処理を行う場合は少ない。
ところで、プログラミング言語の中には、ポインタ変数によって配列を指すことができるものもある。ポインタ変数が指す配列は、実行時に動的に変更され得る。このため、あるポインタ変数が実際に指している配列をソースコードから判定することは容易でない。そこで、コンパイル装置200は、ソースコードに現れるポインタ変数はソースコードに定義されている任意の配列を指す可能性があると仮定して、定義領域と参照領域との比較が行われるようにオブジェクトコードを生成する。
図16は、ソースコード例を示す第6の図である。
ソースコード55には、サブルーチンfoo15が記載されている。サブルーチンfoo15は、引数としてk1,k2を取得する。サブルーチンfoo15は、長さがk2+1の実数型の配列bと、実数型の配列を指すポインタ変数a1,a2とを定義する。サブルーチンfoo15は、ポインタ変数a1に対して長さがk2+1の配列を割り当てると共に、ポインタ変数a2がポインタ変数a1と同じ配列を指すように設定する。そして、サブルーチンfoo15は、ループ変数nの値をk1からk2まで1ずつ増加させながらループを実行する。ループは、ポインタ変数a1が指す配列のn+1番目の要素の定義と、ポインタ変数a2が指す配列のn番目の要素の参照とを含む。
ここで、定義に係る変数名は「a1」であり、参照に係る変数名は「a2」であるため、この定義される配列と参照される配列とは異なるようにも見える。しかし、実際にはポインタ変数a2はポインタ変数a1と同じ配列を指しているため、この定義される配列と参照される配列とは同一である。この場合、「a1」に対応する定義領域と「a2」に対応する参照領域とを比較して、ループの並列化可否を判定することが好ましい。
ただし、コンパイル装置200は、ポインタ変数a1,a2が指す配列の同一性をコンパイル時に静的に判定することは難しい。そのため、コンパイル装置200は、ポインタ変数a1,a2はソースコード55に現れる任意の配列を指すものと仮定する。すなわち、コンパイル装置200は、ポインタ変数a2が指す配列は、配列bと同一であり、ポインタ変数a1が指す配列とも同一であると仮定する。この場合、コンパイル装置200は、配列bの定義領域とポインタ変数a2の参照領域との間の比較と、ポインタ変数a1の定義領域とポインタ変数a2の参照領域との間の比較とが行われるように、オブジェクトコードを生成する。なお、定義領域および参照領域は実行時のメモリアドレスによって表現されるため、異なる配列間の比較は実行時に重複なしと判定されることになる。
次に、並列計算装置100およびコンパイル装置200の機能について説明する。
図17は、並列計算装置とコンパイル装置の機能例を示すブロック図である。
並列計算装置100は、アドレス情報記憶部121、ループ前検査部122、ループ内検査部123およびメッセージ表示部124を有する。アドレス情報記憶部121は、RAM102またはHDD103に確保した記憶領域を用いて実現できる。ループ前検査部122およびループ内検査部123は、オブジェクトコードから呼び出されるライブラリであるプログラムモジュールを用いて実現できる。ライブラリは、例えば、CPUコア101a〜101dの何れかによって実行される。ライブラリを実行するCPUコアは、並列に動作する複数のスレッドのうちの1つを実行するCPUコアであってもよい。メッセージ表示部124は、プログラムモジュールとして実現できる。
アドレス情報記憶部121は、アドレス情報を記憶する。アドレス情報は、ループ内検査部123によって生成されてアドレス情報記憶部121に格納され、ループ内検査部123から読み出される。アドレス情報は、定義された配列の要素のアドレス(個別定義アドレス)と、参照された配列の要素のアドレス(個別参照アドレス)とを含む。
ループ前検査部122は、コンパイル装置200が生成したオブジェクトコードからループの実行直前に呼び出される。ループ前検査部122は、連続領域の定義、連続領域の参照、規則的領域の定義および規則的領域の参照に関するパラメータを取得する。パラメータは、「引数」や「変数」などと呼ぶこともできる。このパラメータの中には、コンパイル時には値が未確定であり実行時に値が確定するものが含まれ得る。ループ前検査部122は、取得したパラメータに基づいて、連続的な定義領域、連続的な参照領域、規則的な定義領域および規則的な参照領域を算出する。ループ前検査部122は、連続的または規則的な定義領域と連続的または規則的な参照領域とを比較し、ループの並列化可否を判定する。前述のように、定義領域と参照領域とが一部重複する場合は並列化不可と判定され、両者が一致するかまたは重複しない場合は並列化可能と判定される。
ループ内検査部123は、コンパイル装置200が生成したオブジェクトコードからループ内で呼び出される。このため、ループ内検査を行う場合には、ループの繰り返し処理1回につき1回以上、ループ内検査部123が呼び出されることになる。ただし、前述のように、多くの定義領域および参照領域は連続領域かまたは規則的領域に該当するため、ループ内検査部123が呼び出される可能性は低いと期待できる。ループ内検査部123は、個別定義アドレスや個別参照アドレスなど、ループ内検査に用いる情報を取得する。連続的な定義領域、連続的な参照領域、規則的な定義領域および規則的な参照領域に関する情報は、ループ前検査部122から取得するようにしてもよい。
ループ内検査部123は、個別定義アドレスおよび個別参照アドレスをアドレス情報記憶部121に格納する。また、ループ内検査部123は、個別定義アドレスと、連続的な参照領域および規則的な参照領域とを比較する。前者が後者に包含される場合には、原則として並列化不可と判定される。また、ループ内検査部123は、個別定義アドレスと、アドレス情報記憶部121に蓄積された個別参照アドレスとを比較する。両者が一致する場合には、原則として並列化不可と判定される。また、ループ内検査部123は、個別参照アドレスと、連続的な定義領域および規則的な定義領域とを比較する。前者が後者に包含される場合には、原則として並列化不可と判定される。また、ループ内検査部123は、個別参照アドレスと、アドレス情報記憶部121に蓄積された個別定義アドレスとを比較する。両者が一致する場合には、原則として並列化不可と判定される。
メッセージ表示部124は、ループ前検査部122またはループ内検査部123によってループが並列化不可と判定されると、並列化不可を警告するメッセージを生成する。メッセージ表示部124は、生成したメッセージをディスプレイ111に表示する。ただし、メッセージ表示部124は、生成したメッセージをRAM102やHDD103などに記憶されたログに追記してもよい。また、メッセージ表示部124は、生成したメッセージをネットワーク30を介して他の装置に送信してもよい。また、メッセージ表示部124は、生成したメッセージを音として再生してもよい。
コンパイル装置200は、ソースコード記憶部221、中間コード記憶部222、オブジェクトコード記憶部223、フロントエンド部224、最適化部225およびバックエンド部226を有する。ソースコード記憶部221、中間コード記憶部222およびオブジェクトコード記憶部223は、RAM202またはHDD203に確保した記憶領域を用いて実現できる。フロントエンド部224、最適化部225およびバックエンド部226は、プログラムモジュールを用いて実現できる。
ソースコード記憶部221は、ユーザが作成したソースコード(前述のソースコード41〜49,51〜55など)を記憶する。ソースコードは、FORTRANなどのプログラミング言語を用いて記載されている。ソースコードには、ループが記載されていることがある。ループに対しては、ユーザによって並列化が指示されていることがある。並列化指示文は、プログラミング言語の仕様に定義されたものであってもよいし、OpenMPなどの拡張言語に従ってソースコードに付加されるものであってもよい。
中間コード記憶部222は、ソースコードから変換された中間コードを記憶する。中間コードは、コンパイル装置200の内部で使用される中間言語を用いて記載されている。オブジェクトコード記憶部223は、ソースコードに対応する機械可読なオブジェクトコードを記憶する。オブジェクトコードは、並列計算装置100によって実行される。
フロントエンド部224は、コンパイルのフロントエンド処理を行う。すなわち、フロントエンド部224は、ソースコード記憶部221からソースコードを読み出し、読み出したソースコードを解析する。ソースコードの解析には、字句解析、構文解析および意味解析が含まれる。フロントエンド部224は、ソースコードに対応する中間コードを生成し、生成した中間コードを中間コード記憶部222に格納する。
また、フロントエンド部224は、ユーザから入力されたコンパイルコマンドに所定のコンパイルオプション(デバッグオプションなど)が付加されていた場合、ループの並列化可否を判定する検査処理の挿入を行う。検査処理の挿入は、ソースコードレベルで行ってもよいし、中間コードレベルで行ってもよい。
フロントエンド部224は、ループ内から配列の定義の命令を抽出し、インデックスやループ変数などの記載に基づいて、定義領域が連続的領域になるか規則的領域になるか非規則的領域になるかを推定する。また、フロントエンド部224は、ループ内から配列の参照の命令を抽出し、インデックスやループ変数などの記載に基づいて、参照領域が連続的領域になるか規則的領域になるか非規則的領域になるかを推定する。フロントエンド部224は、連続的な定義領域、連続的な参照領域、規則的な定義領域および規則的な参照領域が存在する場合、ループ直前に、パラメータの値を算出してライブラリを呼び出す命令を挿入する。また、フロントエンド部224は、非規則的な定義領域および非規則的な参照領域が存在する場合、ループ内に、ライブラリを呼び出す命令を挿入する。
最適化部225は、中間コード記憶部222から中間コードを読み出し、実行効率の高いオブジェクトコードが生成されるように、中間コードに対して各種の最適化を行う。最適化には、複数のCPUコアを利用した並列化が含まれる。最適化部225は、中間コードの中から並列化可能な処理を検出し、複数のスレッドが並列に実行されるように中間コードを書き換える。ループ内で検査処理を行わない場合、そのループは並列化できる可能性がある。すなわち、n回繰り返される処理が分割され、n回のうちのi回目の処理とj回目の処理とが異なるCPUコアによって実行され得る。一方、ループ内で検査処理を行う場合、繰り返し処理の間に依存関係が生じるためそのループは並列化されない。
バックエンド部226は、コンパイルのバックエンド処理を行う。すなわち、バックエンド部226は、中間コード記憶部222から最適化済みの中間コードを読み出し、読み出した中間コードをオブジェクトコードに変換する。バックエンド部226は、中間コードからアセンブリ言語で記述されたアセンブリコードを生成し、アセンブリコードをオブジェクトコードに変換するようにしてもよい。バックエンド部226は、生成したオブジェクトコードをオブジェクトコード記憶部223に格納する。
図18は、ライブラリ呼び出しのパラメータ例を示す図である。
コンパイル装置200によって生成されるオブジェクトコードは、ループの実行直前に、図18に示すようなパラメータ81〜84の値を配列毎に算出し、ライブラリ(ループ前検査部122)を呼び出す。ライブラリの呼び出しは、例えば、配列単位で行われる。すなわち、同一の配列についての定義および参照についての情報は纏められる。
パラメータ81は、定義領域が連続領域になるような配列へのアクセス(連続領域定義)に関するパラメータである。パラメータ81は、定義項目の個数を含む。定義項目の個数は、ループ内で行われる連続領域定義の個数を示す。定義項目の個数は、コンパイル時に算出できる。パラメータ81は、定義項目毎に、先頭アドレスと領域サイズとを含む。先頭アドレスは、連続領域定義によってアクセスされる配列の要素のうち先頭の要素を示すメモリアドレスである。領域サイズは、連続領域定義によってアクセスされる定義領域の大きさ(バイト数)である。先頭アドレスおよび領域サイズは、実行時に算出される。
例えば、図6に示したソースコード41の場合、「a(n+in)」への値の代入が連続領域定義に該当する。この場合、定義項目の個数は1、先頭アドレスはa(2)を示すメモリアドレス、領域サイズは4バイト×1000=4000バイトとなる。なお、ここでは、実数型の要素1個は4バイトで表現されるものとしている。また、配列の定義が連続領域定義であるか否かの判定方法については後述する。
パラメータ82は、参照領域が連続領域になるような配列へのアクセス(連続領域参照)に関するパラメータである。パラメータ82は、参照項目の個数を含む。参照項目の個数は、ループ内で行われる連続領域参照の個数を示す。参照項目の個数は、コンパイル時に算出できる。パラメータ82は、参照項目毎に、先頭アドレスと領域サイズとを含む。先頭アドレスは、連続領域参照によってアクセスされる配列の要素のうち先頭の要素を示すメモリアドレスである。領域サイズは、連続領域参照によってアクセスされる参照領域の大きさ(バイト数)である。先頭アドレスおよび領域サイズは、実行時に算出される。
例えば、図6に示したソースコード41の場合、「a(n)」の値の取得が連続領域参照に該当する。この場合、参照項目の個数は1、先頭アドレスはa(1)を示すメモリアドレス、領域サイズは4バイト×1000=4000バイトとなる。なお、配列の参照が連続領域参照であるか否かの判定方法については後述する。
パラメータ83は、定義領域が規則的領域になるような配列へのアクセス(規則的領域定義)に関するパラメータである。パラメータ83は、定義項目の個数を含む。定義項目の個数は、ループ内で行われる規則的領域定義の個数を示す。定義項目の個数は、コンパイル時に算出できる。パラメータ83は、定義項目毎に、先頭アドレスと要素サイズと次元数とを含む。先頭アドレスは、規則的領域定義によってアクセスされる配列の要素のうち先頭の要素を示すメモリアドレスである。先頭アドレスは、実行時に算出される。要素サイズは、配列の要素1個の大きさ(バイト数)である。次元数は、インデックスの次元数である。要素サイズおよび次元数は、コンパイル時に算出される。
パラメータ83は、インデックスの次元毎に、繰り返し回数とアドレス増分とを含む。繰り返し回数は、ループを実行した場合にその次元のインデックスの値が何通りに変化するかを示す。アドレス増分は、その次元のインデックスの値が1つ変化するときのメモリアドレスの増加量である。繰り返し回数およびアドレス増分は、実行時に算出される。
例えば、図13に示したソースコード54の場合、「a(n+in)」への値の代入が規則的領域定義に該当する。この場合、定義項目の個数は1、先頭アドレスはa(2)を示すメモリアドレス、要素サイズは4バイト、次元数は1となる。また、繰り返し回数は(k2−k1+1)/2=500回、アドレス増分は4バイト×2=8バイトとなる。なお、配列の定義が規則的領域定義であるか否かの判定方法については後述する。
パラメータ84は、参照領域が規則的領域になるような配列へのアクセス(規則的領域参照)に関するパラメータである。パラメータ84は、参照項目の個数を含む。参照項目の個数は、ループ内で行われる規則的領域参照の個数を示す。参照項目の個数は、コンパイル時に算出できる。パラメータ84は、参照項目毎に、先頭アドレスと要素サイズと次元数とを含む。先頭アドレスは、規則的領域参照によってアクセスされる配列の要素のうち先頭の要素を示すメモリアドレスである。先頭アドレスは、実行時に算出される。要素サイズは、配列の要素1個の大きさ(バイト数)である。次元数は、インデックスの次元数である。要素サイズおよび次元数は、コンパイル時に算出される。
パラメータ84は、インデックスの次元毎に、繰り返し回数とアドレス増分とを含む。繰り返し回数は、ループを実行した場合にその次元のインデックスの値が何通りに変化するかを示す。アドレス増分は、その次元のインデックスの値が1つ変化するときのメモリアドレスの増加量である。繰り返し回数およびアドレス増分は、実行時に算出される。
例えば、図13に示したソースコード54の場合、「a(n)」の値の取得が規則的領域参照に該当する。この場合、参照項目の個数は1、先頭アドレスはa(1)を示すメモリアドレス、要素サイズは4バイト、次元数は1となる。また、繰り返し回数は(k2−k1+1)/2=500回、アドレス増分は4バイト×2=8バイトとなる。なお、配列の参照が規則的領域参照であるか否かの判定方法については後述する。
図19は、エラーメッセージの表示例を示す図である。
エラーメッセージ91は、ループが並列化不可と判定された場合にメッセージ表示部124によって生成される。エラーメッセージ91は、例えば、ユーザがプログラムの起動コマンドを入力したコマンド入力ウィンドウに表示される。一例として、ソースコードの13行目に記載された配列の定義に対応する定義領域とソースコードの14行目に記載された配列の参照に対応する参照領域とが一部重複していたとする。この場合、例えば、「行番号13の変数名aと行番号14の変数名aの引用は、特定の繰り返しの実行に依存しています。このループの実行結果は不定です。」という文が表示される。この文は、RAM102やHDD103などに記憶されたエラーログに追記されてもよい。
次に、コンパイル、ループ前検査およびループ内検査の手順について説明する。
図20は、コンパイルの手順例を示すフローチャートである。
ここでは、主に検査機能の追加に関する処理について説明する。
(S110)フロントエンド部224は、未選択のループが存在するか判断する。未選択のループが存在する場合はステップS111に処理が進み、未選択のループが存在しない場合はフロントエンド部224の処理が終了する。
(S111)フロントエンド部224は、ループを1つ選択する。
(S112)フロントエンド部224は、ステップS111で選択したループが並列化指示のあるループであるか判断する。ループに対して並列化を指示する構文は、プログラミング言語の仕様に規定されていることもあるし、そのプログラミング言語とは異なる拡張言語によって規定されていることもある。並列化指示のあるループである場合はステップS113に処理が進み、それ以外の場合はステップS110に処理が進む。
(S113)フロントエンド部224は、ステップS111で選択したループの中から配列の定義を示す定義項目を抽出し、定義項目を列挙した定義項目リストを生成する。定義項目は、例えば、代入文の左辺(等号の左側)に記載された項目であり、配列を示す変数名とインデックスとを含む。また、フロントエンド部224は、ステップS111で選択したループの中から配列の参照を示す参照項目を抽出し、参照項目を列挙した参照項目リストを生成する。参照項目は、例えば、代入文の右辺(等号の右側)に記載されたものであり、配列を示す変数名とインデックスとを含む。定義項目および参照項目には、配列を指すポインタ変数を用いたものが含まれる。
(S114)フロントエンド部224は、ステップS113で生成した定義項目リストと参照項目リストとを比較し、片方のリストのみに現れる変数名を検出する。そして、フロントエンド部224は、検出した変数名を含む定義項目を定義項目リストから削除し、検出した変数名を含む参照項目を参照項目リストから削除する。定義のみ行われ参照されない配列、および、参照のみ行われ定義されない配列は、繰り返し処理に依存関係を生じさせないためである。ただし、ポインタ変数は任意の配列を指すことができるため、ポインタ変数の変数名を含む定義項目および参照項目は削除対象としない。
(S115)フロントエンド部224は、定義項目リストに含まれる定義項目および参照項目リストに含まれる参照項目を、変数名によって分類する。フロントエンド部224は、変数名が同じ定義項目および参照項目の間でインデックスが全て同一である場合、その定義項目を定義項目リストから削除し、その参照項目を参照項目リストから削除する。インデックスが同一であれば、i回目の処理で定義される要素とj回目の処理で参照される要素とが同一になることはないからである(i,jは異なる正の整数)。ただし、ポインタ変数の変数名を含む定義項目および参照項目は削除対象としない。
(S116)フロントエンド部224は、定義項目リストの中で、変数名とインデックスが同じ定義項目を纏める。また、フロントエンド部224は、参照項目リストの中で、変数名とインデックスが同じ参照項目を纏める。
(S117)フロントエンド部224は、定義項目リストの中から定義領域が連続領域になる定義項目を抽出する。定義領域が連続領域になる定義項目は、以下に示す条件#1を満たす定義項目である。また、フロントエンド部224は、参照項目リストの中から参照領域が連続領域になる参照項目を抽出する。参照領域が連続領域になる参照項目は、以下に示す条件#1を満たす参照項目である。
条件#1は、次の(1a),(1b),(1c)の全てを満たすことである。(1a)インデックスの中にループ変数が1つだけ現れる。(1b)インデックスがループ変数単独であるか、または、ループ変数と定数または他の変数との加減算として表されている。(1c)ループ変数の増分が省略されているか、または、ループ変数の増分が1に指定されている。例えば、「a(n)」や「a(n+in)」は上記(1b)を満たす一方、「a(2n)」は上記(1b)を満たさない。また、例えば、「DO CONCURRENT(n=1:1000:1)」は上記(1c)を満たす一方、「DO CONCURRENT(n=1:1000:2)」は上記(1c)を満たさない。
フロントエンド部224は、抽出した定義項目について図18のパラメータ81を生成し、抽出した参照項目について図18のパラメータ82を生成する。ただし、パラメータ81,82には、コンパイル時に決定できる値が含まれていることもあるし、コンパイル時に決定されない値が含まれていることもある。後者については、実行時に決定される変数の値からパラメータの値を算出する方法が特定される。例えば、図6のソースコード41の場合、領域サイズは(k2−k1+1)×4によって算出できる。
(S118)フロントエンド部224は、定義項目リストの中から定義領域が規則的領域になる定義項目を抽出する。定義領域が規則的領域になる定義項目は、以下に示す条件#2または条件#3を満たす定義項目である。また、フロントエンド部224は、参照項目リストの中から参照領域が規則的領域になる参照項目を抽出する。参照領域が規則的領域になるものは、以下に示す条件#2または条件#3を満たす参照項目である。
条件#2は、次の(2a),(2b)の両方を満たすことである。(2a)次元数が2以上であり、2以上のループ変数が互いに異なる次元に現れる。(2b)ループ変数が現れる次元それぞれについて、インデックスがループ変数単独であるか、または、ループ変数と定数または他の変数との加減算として表されている。例えば、「DO DONCURRENT(n1=1:1000,n2=1:1000)…a(n1+k1,n2)」は、上記(2a)および上記(2b)を満たす。
条件#3は、次の(3a),(3b),(3c)の全てを満たすことである。(3a)インデックスの中にループ変数が1つだけ現れる。(3b)インデックスがループ変数単独であるか、または、ループ変数と定数または他の変数との加減算として表されている。(3c)ループ変数の増分が1より大きいか、または、ループ変数の増分が変数であり1より大きい可能性がある。例えば、「DO DONCURRENT(n=1:1000:k)…a(n)」は、上記(3a)〜(3c)を満たす。
フロントエンド部224は、抽出した定義項目について図18のパラメータ83を生成し、抽出した参照項目について図18のパラメータ84を生成する。ただし、パラメータ83,84には、コンパイル時に決定できる値が含まれていることもあるし、コンパイル時に決定されない値が含まれていることもある。後者については、実行時に決定される変数の値からパラメータの値を算出する方法が特定される。例えば、図13のソースコード54の場合、繰り返し回数は(k2−k1+1)/2によって算出できる。
(S119)フロントエンド部224は、ステップS117で生成したパラメータ81,82およびステップS118で生成したパラメータ83,84について、同じ配列(同じ変数名)に関するパラメータ同士を纏める。ただし、ポインタ変数は任意の配列を指す可能性があるため、フロントエンド部224は、ポインタ変数が指す配列は他の全ての配列と同一であると仮定する。フロントエンド部224は、配列毎(変数名毎)に、ループの直前にライブラリ呼び出し命令を挿入する。ライブラリ呼び出しでは、その配列に対応するパラメータ81〜84が引数として指定される。
(S120)フロントエンド部224は、ステップS119で生成したライブラリ呼び出しによって全ての定義項目と参照項目がカバーされるか判断する。すなわち、フロントエンド部224は、定義項目リストに含まれる全ての定義項目および参照項目リストに含まれる全ての参照項目が上記の条件#1〜#3の何れかに該当するか判断する。全ての定義項目および参照項目が条件#1〜#3の何れかに該当する場合、フロントエンド部224の処理が終了する。条件#1〜#3の何れにも該当しない定義項目または参照項目が存在する場合、ステップS121に処理が進む。
(S121)フロントエンド部224は、カウンタCを1に初期化する命令をループ直前に挿入する。また、フロントエンド部224は、条件#1〜#3に該当しない定義項目について、ループ内のその定義項目が現れる場所にライブラリ呼び出し命令を挿入する。このライブラリ呼び出しでは、定義される要素のアドレスが引数として渡される。また、フロントエンド部224は、条件#1〜#3に該当しない参照項目について、ループ内のその参照項目が現れる場所にライブラリ呼び出し命令を挿入する。このライブラリ呼び出しでは、参照される要素のアドレスが引数として渡される。また、フロントエンド部224は、カウンタCに1を加算する命令をループ終端に挿入する。
図21は、ループ前検査の手順例を示すフローチャートである。
(S210)ループ前検査部122は、パラメータ81が示す連続的な定義領域とパラメータ82が示す連続的な参照領域とを比較し、繰り返し処理の依存性を検査する。この「連続・連続間検査」については図22を用いて説明する。
(S211)ループ前検査部122は、パラメータ81が示す連続的な定義領域とパラメータ84が示す規則的な参照領域とを比較し、繰り返し処理の依存性を検査する。この「連続・規則性間検査」については図23を用いて説明する。
(S212)ループ前検査部122は、パラメータ83が示す規則的な定義領域とパラメータ82が示す連続的な参照領域とを比較し、繰り返し処理の依存性を検査する。この「規則性・連続間検査」については図24を用いて説明する。
(S213)ループ前検査部122は、パラメータ83が示す規則的な定義領域とパラメータ84が示す規則的な参照領域とを比較し、繰り返し処理の依存性を検査する。この「規則性・規則性間検査」については図25を用いて説明する。
図22は、連続・連続間検査の手順例を示すフローチャートである。
(S220)ループ前検査部122は、パラメータ81(連続領域定義に関するパラメータ)の中から定義項目を1つ選択する。
(S221)ループ前検査部122は、パラメータ82(連続領域参照に関するパラメータ)の中から参照項目を1つ選択する。
(S222)ループ前検査部122は、定義項目の先頭アドレスと参照項目の先頭アドレスとが同一であり、かつ、定義項目の領域サイズと参照項目の領域サイズが同一であるか判断する。先頭アドレスと領域サイズの両方が同一である場合、定義領域と参照領域が完全一致する。この場合、ステップS225に処理が進む。先頭アドレスと領域サイズの少なくとも一方が異なる場合、ステップS223に処理が進む。
(S223)ループ前検査部122は、定義項目が示す定義領域と参照項目が示す参照領域とが一部重複するか判断する。例えば、ループ前検査部122は、定義項目の先頭アドレスに定義項目の領域サイズを加えて末尾アドレスを算出する。定義項目の先頭アドレスと末尾アドレスの間に参照項目の先頭アドレスがある場合、定義領域と参照領域が一部重複している。また、ループ前検査部122は、参照項目の先頭アドレスに参照項目の領域サイズを加えて末尾アドレスを算出する。参照項目の先頭アドレスと末尾アドレスの間に定義項目の先頭アドレスがある場合、定義領域と参照領域が一部重複している。定義領域と参照領域が一部重複する場合はステップS224に処理が進み、定義領域と参照領域が重複していない場合はステップS225に処理が進む。
(S224)メッセージ表示部124は、エラーメッセージ91を生成する。メッセージ表示部124は、エラーメッセージ91をディスプレイ111に表示する。
(S225)ループ前検査部122は、パラメータ82に未選択の参照項目があるか判断する。未選択の参照項目がある場合はステップS221に処理が進み、全ての参照項目を選択した場合はステップS226に処理が進む。
(S226)ループ前検査部122は、パラメータ81に未選択の定義項目があるか判断する。未選択の定義項目がある場合はステップS220に処理が進み、全ての定義項目を選択した場合は連続・連続間検査が終了する。
図23は、連続・規則性間検査の手順例を示すフローチャートである。
(S230)ループ前検査部122は、パラメータ81(連続領域定義に関するパラメータ)の中から定義項目を1つ選択する。
(S231)ループ前検査部122は、パラメータ84(規則的領域参照に関するパラメータ)の中から参照項目を1つ選択する。
(S232)ループ前検査部122は、参照項目に基づいて規則的にアクセスされる各領域のアドレス(参照アドレス)を算出し、定義項目が示す定義領域と比較する。例えば、ループ前検査部122は、定義項目の先頭アドレスに定義項目の領域サイズを加えて末尾アドレスを算出する。また、ループ前検査部122は、参照項目の先頭アドレスにアドレス増分を繰り返し加算していくことで、全ての参照アドレスを算出する。ループ前検査部122は、各参照アドレスが、定義項目の先頭アドレスおよび末尾アドレスによって特定される定義領域に包含されるか判定する。
(S233)ループ前検査部122は、全ての参照アドレスが定義領域外であるか判断する。全ての参照アドレスが定義領域外である場合、定義領域と参照領域とが重複しない。全ての参照アドレスが定義領域外である場合はステップS236に処理が進み、少なくとも1つの参照アドレスが定義領域内である場合はステップS234に処理が進む。
(S234)ループ前検査部122は、全ての参照アドレスが定義領域内であるか判断する。全ての参照アドレスが定義領域内である場合、定義領域と参照領域とが完全一致する。全ての参照アドレスが定義領域内である場合、ステップS236に処理が進む。一部の参照アドレスが定義領域内かつ一部の参照アドレスが定義領域外である場合、すなわち、定義領域と参照領域とが一部重複する場合、ステップS235に処理が進む。
(S235)メッセージ表示部124は、エラーメッセージ91を生成する。メッセージ表示部124は、エラーメッセージ91をディスプレイ111に表示する。
(S236)ループ前検査部122は、パラメータ84に未選択の参照項目があるか判断する。未選択の参照項目がある場合はステップS231に処理が進み、全ての参照項目を選択した場合はステップS237に処理が進む。
(S237)ループ前検査部122は、パラメータ81に未選択の定義項目があるか判断する。未選択の定義項目がある場合はステップS230に処理が進み、全ての定義項目を選択した場合は連続・規則性間検査が終了する。
図24は、規則性・連続間検査の手順例を示すフローチャートである。
(S240)ループ前検査部122は、パラメータ82(連続領域参照に関するパラメータ)の中から参照項目を1つ選択する。
(S241)ループ前検査部122は、パラメータ83(規則的領域定義に関するパラメータ)の中から定義項目を1つ選択する。
(S242)ループ前検査部122は、定義項目に基づいて規則的にアクセスされる各領域のアドレス(定義アドレス)を算出し、参照項目が示す参照領域と比較する。例えば、ループ前検査部122は、参照項目の先頭アドレスに参照項目の領域サイズを加えて末尾アドレスを算出する。また、ループ前検査部122は、定義項目の先頭アドレスにアドレス増分を繰り返し加算していくことで、全ての定義アドレスを算出する。ループ前検査部122は、各定義アドレスが、参照項目の先頭アドレスおよび末尾アドレスによって特定される参照領域に包含されるか判定する。
(S243)ループ前検査部122は、全ての定義アドレスが参照領域外であるか判断する。全ての定義アドレスが参照領域外である場合、定義領域と参照領域とが重複しない。全ての定義アドレスが参照領域外である場合はステップS246に処理が進み、少なくとも1つの定義アドレスが参照領域内である場合はステップS244に処理が進む。
(S244)ループ前検査部122は、全ての定義アドレスが参照領域内であるか判断する。全ての定義アドレスが参照領域内である場合、定義領域と参照領域とが完全一致する。全ての定義アドレスが参照領域内である場合、ステップS246に処理が進む。一部の定義アドレスが参照領域内かつ一部の定義アドレスが参照領域外である場合、すなわち、定義領域と参照領域とが一部重複する場合、ステップS245に処理が進む。
(S245)メッセージ表示部124は、エラーメッセージ91を生成する。メッセージ表示部124は、エラーメッセージ91をディスプレイ111に表示する。
(S246)ループ前検査部122は、パラメータ83に未選択の定義項目があるか判断する。未選択の定義項目がある場合はステップS241に処理が進み、全ての定義項目を選択した場合はステップS247に処理が進む。
(S247)ループ前検査部122は、パラメータ82に未選択の参照項目があるか判断する。未選択の参照項目がある場合はステップS240に処理が進み、全ての参照項目を選択した場合は規則性・連続間検査が終了する。
図25は、規則性・規則性間検査の手順例を示すフローチャートである。
(S250)ループ前検査部122は、パラメータ83(規則的領域定義に関するパラメータ)の中から定義項目を1つ選択する。
(S251)ループ前検査部122は、パラメータ84(規則的領域参照に関するパラメータ)の中から参照項目を1つ選択する。
(S252)ループ前検査部122は、定義領域の先頭から末尾までの全体範囲と参照領域の先頭から末尾までの全体範囲とに重複があるか判断する。例えば、ループ前検査部122は、定義項目の先頭アドレスに定義項目のアドレス増分×(繰り返し回数−1)を加算することで末尾アドレスを算出する。また、ループ前検査部122は、参照項目の先頭アドレスに参照項目のアドレス増分×(繰り返し回数−1)を加算することで末尾アドレスを算出する。ループ前検査部122は、連続・連続間検査の場合と同様に、定義領域の全体範囲と参照領域の全体範囲を比較する。両者に重複がある場合はステップS253に処理が進み、重複がない場合はステップS259に処理が進む。
(S253)ループ前検査部122は、定義項目と参照項目の間で、先頭アドレスと繰り返し回数とアドレス増分の全てが一致するか判断する。先頭アドレスと繰り返し回数とアドレス増分の全てが一致する場合、定義領域と参照領域が完全一致する。全てが一致する場合、ステップS259に処理が進む。先頭アドレスと繰り返し回数とアドレス増分の少なくとも1つが異なる場合、ステップS254に処理が進む。
(S254)ループ前検査部122は、定義項目と参照項目の間で先頭アドレスが一致するか判断する。先頭アドレスが一致する場合はステップS257に処理が進み、先頭アドレスが一致しない場合はステップS255に処理が進む。なお、前者の場合は、繰り返し回数とアドレス増分の少なくとも一方が異なっている。
(S255)ループ前検査部122は、定義項目と参照項目の間で、繰り返し回数とアドレス増分が一致するか判断する。先頭アドレスは異なるが繰り返し回数とアドレス増分は一致する場合、ステップS256に処理が進む。先頭アドレスに加えて繰り返し回数とアドレス増分の少なくとも一方も異なる場合、ステップS257に処理が進む。
(S256)ループ前検査部122は、定義項目の先頭アドレスと参照項目の先頭アドレスの差を算出し、差がアドレス増分の整数倍であるか判断する。繰り返し回数とアドレス増分が一致し、かつ、先頭アドレスの差がアドレス増分の整数倍であれば、定義領域と参照領域は一部重複する。この場合、ステップS258に処理が進む。一方、繰り返し回数とアドレス増分が一致し、かつ、先頭アドレスの差がアドレス増分の整数倍でなければ、定義領域と参照領域は重複しない。この場合、ステップS259に処理が進む。
(S257)ループ前検査部122は、定義項目に基づいて規則的にアクセスされる各領域のアドレス(定義アドレス)を算出する。また、ループ前検査部122は、参照項目に基づいて規則的にアクセスされる各領域のアドレス(参照アドレス)を算出する。ループ前検査部122は、定義アドレスと参照アドレスを網羅的に比較し、一部の定義アドレスと参照アドレスの組のみが一致するか判断する。一部の定義アドレスと参照アドレスの組のみが一致する場合、ステップS258に処理が進む。全ての定義アドレスについてそれと一致する参照アドレスが存在しないか、または、全ての定義アドレスについてそれと一致する参照アドレスが存在する場合、ステップS259に処理が進む。なお、多くの定義項目および参照項目は、ステップS252〜S256の判断条件によってステップS258に進むか否か判断できるため、ステップS257が実行される可能性は低い。
(S258)メッセージ表示部124は、エラーメッセージ91を生成する。メッセージ表示部124は、エラーメッセージ91をディスプレイ111に表示する。
(S259)ループ前検査部122は、パラメータ84に未選択の参照項目があるか判断する。未選択の参照項目がある場合はステップS251に処理が進み、全ての参照項目を選択した場合はステップS260に処理が進む。
(S260)ループ前検査部122は、パラメータ83に未選択の定義項目があるか判断する。未選択の定義項目がある場合はステップS250に処理が進み、全ての定義項目を選択した場合は規則性・規則性間検査が終了する。
図26は、ループ内検査の手順例を示すフローチャートである。
(S310)並列計算装置100は、コンパイル装置200によって生成されたオブジェクトコードに基づいて、ループの実行前にカウンタCを1に初期化する。
(S311)並列計算装置100は、コンパイル装置200によって生成されたオブジェクトコードに基づいて、ループ前に検査されなかった定義項目に対応して、ループ内においてループ内検査部123を呼び出す。ループ内検査部123は、個別定義検査を実行する。「個別定義検査」については図27を用いて説明する。
(S312)並列計算装置100は、コンパイル装置200によって生成されたオブジェクトコードに基づいて、ループ前に検査されなかった参照項目に対応して、ループ内においてループ内検査部123を呼び出す。ループ内検査部123は、個別参照検査を実行する。「個別参照検査」については図28を用いて説明する。
(S313)並列計算装置100は、コンパイル装置200によって生成されたオブジェクトコードに基づいて、カウンタCに1を加算する。
(S314)並列計算装置100は、コンパイル装置200によって生成されたオブジェクトコードに基づいて、ループの終了条件を満たしたか(例えば、ループ変数の値が上限値に達したか)判断する。ループの終了条件を満たした場合はループ内検査が終了し、ループの終了条件を満たしていない場合はステップS311に処理が進む。
図27は、個別定義検査の手順例を示すフローチャートである。
(S320)ループ内検査部123は、パラメータ82が示す参照項目に基づいて、現在のカウンタCに対応する参照アドレス、すなわち、連続的な参照領域のうちループ変数の値が現在と同じときに参照される領域のアドレスを算出する。
(S321)ループ内検査部123は、ループ内検査部123が呼び出されるときに定義された領域のアドレス(最新の個別定義アドレス)と、パラメータ82が示す連続的な参照領域とを比較する。また、ループ内検査部123は、最新の個別定義アドレスとステップS320の参照アドレスとを比較する。ループ内検査部123は、最新の個別定義アドレスが連続的な参照領域内にあり、かつ、ステップS320の参照アドレスと異なるか判断する。上記条件を満たす場合、最新の個別定義アドレスの示す要素が、ループ変数の値が異なる処理において参照されることになる。この条件を満たす場合はステップS326に処理が進み、満たさない場合はステップS322に処理が進む。
(S322)ループ内検査部123は、パラメータ84が示す参照項目に基づいて、現在のカウンタCに対応する参照アドレス、すなわち、規則的な参照領域のうちループ変数の値が現在と同じときに参照される領域のアドレスを算出する。
(S323)ループ内検査部123は、最新の個別定義アドレスとパラメータ84が示す規則的な参照領域とを比較する。また、ループ内検査部123は、最新の個別定義アドレスとステップS322の参照アドレスとを比較する。ループ内検査部123は、最新の個別定義アドレスが規則的な参照領域内にあり、かつ、ステップS322の参照アドレスと異なるか判断する。上記条件を満たす場合、最新の個別定義アドレスの示す要素が、ループ変数の値が異なる処理において参照されることになる。この条件を満たす場合はステップS326に処理が進み、満たさない場合はステップS324に処理が進む。
(S324)ループ内検査部123は、最新の個別定義アドレスが、アドレス情報記憶部121に登録されている個別参照アドレスの何れかと一致するか判断する。また、ループ内検査部123は、現在のカウンタCが、当該一致する個別参照アドレスに対応付けられているカウンタの値と異なるか判断する。この条件を満たす場合はステップS326に処理が進み、満たさない場合はステップS325に処理が進む。
(S325)ループ内検査部123は、最新の個別定義アドレスと現在のカウンタCを対応付けて、アドレス情報記憶部121に登録する。
(S326)メッセージ表示部124は、エラーメッセージ91を生成する。メッセージ表示部124は、エラーメッセージ91をディスプレイ111に表示する。
図28は、個別参照検査の手順例を示すフローチャートである。
(S330)ループ内検査部123は、パラメータ81が示す定義項目に基づいて、現在のカウンタCに対応する定義アドレス、すなわち、連続的な定義領域のうちループ変数の値が現在と同じときに定義される領域のアドレスを算出する。
(S331)ループ内検査部123は、ループ内検査部123が呼び出されるときに参照された領域のアドレス(最新の個別参照アドレス)と、パラメータ81が示す連続的な定義領域とを比較する。また、ループ内検査部123は、最新の個別参照アドレスとステップS330の定義アドレスとを比較する。ループ内検査部123は、最新の個別参照アドレスが連続的な定義領域内にあり、かつ、ステップS330の定義アドレスと異なるか判断する。上記条件を満たす場合、最新の個別参照アドレスの示す要素が、ループ変数の値が異なる処理において定義されることになる。この条件を満たす場合はステップS336に処理が進み、満たさない場合はステップS332に処理が進む。
(S332)ループ内検査部123は、パラメータ83が示す定義項目に基づいて、現在のカウンタCに対応する定義アドレス、すなわち、規則的な定義領域のうちループ変数の値が現在と同じときに定義される領域のアドレスを算出する。
(S333)ループ内検査部123は、最新の個別参照アドレスとパラメータ83が示す規則的な定義領域とを比較する。また、ループ内検査部123は、最新の個別参照アドレスとステップS332の定義アドレスとを比較する。ループ内検査部123は、最新の個別参照アドレスが規則的な定義領域内にあり、かつ、ステップS332の定義アドレスと異なるか判断する。上記条件を満たす場合、最新の個別参照アドレスの示す要素が、ループ変数の値が異なる処理において定義されることになる。この条件を満たす場合はステップS336に処理が進み、満たさない場合はステップS334に処理が進む。
(S334)ループ内検査部123は、最新の個別参照アドレスが、アドレス情報記憶部121に登録されている個別定義アドレスの何れかと一致するか判断する。また、ループ内検査部123は、現在のカウンタCが、当該一致する個別定義アドレスに対応付けられているカウンタの値と異なるか判断する。この条件を満たす場合はステップS336に処理が進み、満たさない場合はステップS335に処理が進む。
(S335)ループ内検査部123は、最新の個別参照アドレスと現在のカウンタCを対応付けて、アドレス情報記憶部121に登録する。
(S336)メッセージ表示部124は、エラーメッセージ91を生成する。メッセージ表示部124は、エラーメッセージ91をディスプレイ111に表示する。
第3の実施の形態の情報処理システムによれば、定義領域と参照領域が引数に依存する場合であっても、両者がそれぞれ連続領域または規則的領域であれば、ループの実行直前に定義領域と参照領域とを効率的に比較できる。そして、定義領域と参照領域が一部重複する場合には、ループが並列化不可と判定されてエラーメッセージ91が表示される。
多くの定義領域および参照領域は、連続領域になるかまたは規則的領域になると期待される。そのため、ループ内で個々のアドレスを比較して並列化可否を判定する可能性が低くなり、デバッグ用のオブジェクトコードにおいてもループを並列化できる可能性が高くなる。その結果、デバッグ用のオブジェクトコードの実行時間を短縮できる。また、アクセスされた領域のアドレスを網羅的に比較しなくてもよく、並列計算装置100の負荷を軽減できる。このように、ループの並列化に関するソースコードの誤り(並列化不可のループに対して並列化が指示されていること)を効率的に検出できる。
なお、前述のように、第1の実施の形態の情報処理は、並列計算装置10にプログラムを実行させることで実現できる。第2の実施の形態の情報処理は、コンパイル装置20にプログラムを実行させることで実現できる。第3の実施の形態の情報処理は、並列計算装置100およびコンパイル装置200にプログラムを実行させることで実現できる。
プログラムは、コンピュータ読み取り可能な記録媒体(例えば、記録媒体113,213)に記録しておくことができる。記録媒体として、例えば、磁気ディスク、光ディスク、光磁気ディスク、半導体メモリなどを使用できる。磁気ディスクには、FDおよびHDDが含まれる。光ディスクには、CD、CD−R(Recordable)/RW(Rewritable)、DVDおよびDVD−R/RWが含まれる。プログラムは、可搬型の記録媒体に記録されて配布されることがある。その場合、可搬型の記録媒体からHDDなどの他の記録媒体(例えば、HDD103,203)にプログラムをコピーして実行してもよい。