(57)【要約】【課題】ループの並列化に関するプログラムの誤りを効率的に検出する。【解決手段】コード１３はループ１３ａを含む。ループ１３ａは、配列１３ｂの中のインデックス１３ｃが示す要素を更新する更新処理と配列１３ｂの中のインデックス１３ｄが示す要素を参照する参照処理とを含み、インデックス１３ｃおよびインデックス１３ｄの少なくとも一方が実行時に値の決まるパラメータに依存する。演算部１２は、ループ１３ａが実行される前に、実行時におけるパラメータの値に基づいて、更新処理によって更新される範囲１４ａと参照処理によって参照される範囲１４ｂとを算出する。演算部１２は、範囲１４ａと範囲１４ｂとを比較し、範囲１４ａと範囲１４ｂとが部分的に重複する場合にループ１３ａが並列化不可であることを示す警告１５を出力する。【選択図】図１
2016224812.tif 000002
【特許請求の範囲】
【請求項１】
配列の中の第１のインデックスが示す要素を更新する更新処理と前記配列の中の第２のインデックスが示す要素を参照する参照処理とを含むループであって、前記第１のインデックスおよび前記第２のインデックスの少なくとも一方が実行時に値の決まるパラメータに依存するループを含むコードを記憶する記憶部と、
前記コードの実行が開始されてから前記ループが実行される前に、実行時における前記パラメータの値に基づいて、前記配列の中の前記更新処理によって更新される要素の第１の範囲と前記配列の中の前記参照処理によって参照される要素の第２の範囲とを算出し、前記第１の範囲と前記第２の範囲とを比較し、前記第１の範囲と前記第２の範囲とが部分的に重複する場合に前記ループが並列化不可であることを示す警告を出力する演算部と、
を有する並列計算装置。
【請求項２】
前記演算部は、前記第１の範囲と前記第２の範囲とが一致する場合および前記第１の範囲と前記第２の範囲とが重複しない場合、前記ループが並列化可能であると判定する、
請求項１記載の並列計算装置。
【請求項３】
前記第１の範囲および前記第２の範囲はそれぞれ、前記配列に含まれる複数の要素の中の連続した要素の集合または規則的に離れた要素の集合を示し、
前記演算部は、前記ループが実行される前に、前記第１のインデックスの連続性または規則性に基づいて前記第１の範囲を算出し、前記第２のインデックスの連続性または規則性に基づいて前記第２の範囲を算出する、
請求項１または２記載の並列計算装置。
【請求項４】
コンピュータが実行する並列処理方法であって、
配列の中の第１のインデックスが示す要素を更新する更新処理と前記配列の中の第２のインデックスが示す要素を参照する参照処理とを含むループであって、前記第１のインデックスおよび前記第２のインデックスの少なくとも一方が実行時に値の決まるパラメータに依存するループを含むコードの実行を開始し、
前記コードの実行を開始してから前記ループを実行する前に、実行時における前記パラメータの値に基づいて、前記配列の中の前記更新処理によって更新される要素の第１の範囲と前記配列の中の前記参照処理によって参照される要素の第２の範囲とを算出し、
前記第１の範囲と前記第２の範囲とを比較し、前記第１の範囲と前記第２の範囲とが部分的に重複する場合に前記ループが並列化不可であることを示す警告を出力する、
並列処理方法。
【請求項５】
コンピュータに、
配列の中の第１のインデックスが示す要素を更新する更新処理と前記配列の中の第２のインデックスが示す要素を参照する参照処理とを含むループであって、前記第１のインデックスおよび前記第２のインデックスの少なくとも一方が実行時に値の決まるパラメータに依存するループを含むコードの実行が開始されてから、前記ループが実行される前に、実行時における前記パラメータの値に基づいて、前記配列の中の前記更新処理によって更新される要素の第１の範囲と前記配列の中の前記参照処理によって参照される要素の第２の範囲とを算出し、
前記第１の範囲と前記第２の範囲とを比較し、前記第１の範囲と前記第２の範囲とが部分的に重複する場合に前記ループが並列化不可であることを示す警告を出力する、
処理を実行させる並列処理プログラム。
【請求項６】
コンピュータに、
第１のコードの中から、配列の中の第１のインデックスが示す要素を更新する更新処理と前記配列の中の第２のインデックスが示す要素を参照する参照処理とを含むループであって、前記第１のインデックスおよび前記第２のインデックスの少なくとも一方が実行時に値の決まるパラメータに依存するループを検出し、
前記ループが実行される前に前記ループが並列化可能か検査する検査処理が実行されるように、前記第１のコードを第２のコードに変換する処理を実行させ、
前記検査処理は、実行時における前記パラメータの値に基づいて、前記配列の中の前記更新処理によって更新される要素の第１の範囲と前記配列の中の前記参照処理によって参照される要素の第２の範囲とを算出し、前記第１の範囲と前記第２の範囲とを比較し、前記第１の範囲と前記第２の範囲とが部分的に重複する場合に前記ループが並列化不可であることを示す警告を出力することを含む、
コンパイルプログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は並列計算装置、並列処理方法、並列処理プログラムおよびコンパイルプログラムに関する。
【背景技術】
【０００２】
複数のプロセッサ（プロセッサコアと呼ばれるものを含む）を用いて複数のスレッドを並列に実行することができる並列計算装置が使用されることがある。並列計算装置による並列処理の１つとして、ループを並列化したものが考えられる。例えば、ループ内の繰り返し処理のうちのｉ回目の処理とｊ回目の処理（ｉ，ｊは異なる正の整数）とを、異なるスレッドに並列に実行させることが考えられる。
【０００３】
ただし、ループのｉ回目の処理とｊ回目の処理との間に依存関係が存在する場合、当該ループを並列化するとプログラムの意味が並列化前と変わってしまう可能性がある。特に、ループが配列の更新と配列の参照とを含み、ｉ回目の処理において更新される配列の要素とｊ回目の処理において参照される配列の要素とが同一になる場合があり得る。この場合、当該ループを並列化すると、更新と参照の間の実行順序が保証されないために実行結果が不定となり、プログラムの意味が並列化前と変わってしまう。そこで、上記のような依存関係が存在するループは並列化しないことが好ましい。
【０００４】
一方で、ソースコードを作成するにあたって、ユーザがループの並列化を明示的に指定することができる場合がある。例えば、ＦＯＲＴＲＡＮなど、並列実行指示文が言語仕様として規定されているプログラミング言語が存在する。また、ＯｐｅｎＭＰなど、本来の言語仕様とは別に、ソースコードに対して並列実行指示文を付加することができる拡張言語が存在する。このため、並列化することが好ましくないループに対してユーザが誤って並列化を指示してしまい、不具合のあるプログラムが作成される可能性がある。
【０００５】
ループの並列化に関する誤りを検出する方法としては、コンパイラがソースコードをオブジェクトコードに変換する際に静的に検査する方法と、デバッグ用のオブジェクトコードを生成して実行させることで動的に検査する方法とが挙げられる。ループ内で更新される配列の要素および参照される配列の要素を、ソースコードの内容から静的に特定できる場合、コンパイラが静的に誤りを検出し得る。一方、更新される配列の要素および参照される配列の要素が、実行時に値の決まるパラメータに依存する場合、それらの要素をソースコードの内容から静的に特定することは難しい。この場合、検査機能を実装したデバッグ用のオブジェクトコードをコンパイラが生成し、当該デバッグ用のオブジェクトコードを実行することで動的に誤りを検出することが考えられる。
【０００６】
例えば、ループを含むソースコードから、当該ループ内の処理を並列化できるか検査するデバッグ用のオブジェクトコードを生成するコンパイラが提案されている。生成されるオブジェクトコードは、ループ変数＝Ｎ１のときに参照される配列の要素のインデックスと、ループ変数＝Ｎ２のときに更新される配列の要素のインデックスとを、全てのＮ１，Ｎ２の組み合わせについて比較する。少なくとも１つのＮ１，Ｎ２の組み合わせについて上記２つのインデックスが一致した場合、並列化不可と判定される。
【０００７】
また、コンパイラによる最適化方法が提案されている。提案の最適化方法では、コンパイラは、２つの処理が独立しているか（一方の処理が他方の処理の結果を利用していないか）確認し、独立していることが確認できた場合は２つの処理を並列化することを試みる。独立性の確認において、コンパイラは、配列Ｘとループ変数Ｊと定数ａ１，ａ２，ｂ１，ｂ２を用いて記述されたループを検出する。このループ内において、インデックスａ１×Ｊ＋ｂ１を用いた配列Ｘの参照とインデックスａ２×Ｊ＋ｂ２を用いた配列Ｘの参照とが近接しているとする。すると、コンパイラは、任意のループ変数Ｊについて（ａ１−ａ２）×Ｊ＋（ｂ１−ｂ２）＝０となることがあるか計算することで、上記２つのインデックスが配列Ｘの同じ要素を指す可能性を検査する。
【先行技術文献】
【特許文献】
【０００８】
【特許文献１】特開平１−２５１２７４号公報
【特許文献２】特開平５−１９７５６３号公報
【発明の概要】
【発明が解決しようとする課題】
【０００９】
しかし、上記特許文献１に記載された技術では、配列の更新に用いるインデックスの値と配列の参照に用いるインデックスの値の具体的な組み合わせを、網羅的に算出している。すなわち、多重ループを実行することで、更新される配列の要素と参照される配列の要素の具体的な組み合わせを全通り算出している。このため、検査の負荷が大きいという問題がある。また、元のループの中で逐次検査を行うようにした場合、検査機能を実装したままでは当該ループは並列化することが難しくなる。このため、検査機能を実装したデバッグ用のオブジェクトコードの実行時間が、検査機能を実装していない元のオブジェクトコードの実行時間と比べて顕著に長くなってしまうという問題がある。
【００１０】
１つの側面では、本発明は、ループの並列化に関するプログラムの誤りを効率的に検出できるようにする並列計算装置、並列処理方法、並列処理プログラムおよびコンパイルプログラムを提供することを目的とする。
【課題を解決するための手段】
【００１１】
１つの態様では、記憶部と演算部とを有する並列計算装置が提供される。記憶部は、配列の中の第１のインデックスが示す要素を更新する更新処理と配列の中の第２のインデックスが示す要素を参照する参照処理とを含むループであって、第１のインデックスおよび第２のインデックスの少なくとも一方が実行時に値の決まるパラメータに依存するループを含むコードを記憶する。演算部は、コードの実行が開始されてからループが実行される前に、実行時におけるパラメータの値に基づいて、配列の中の更新処理によって更新される要素の第１の範囲と配列の中の参照処理によって参照される要素の第２の範囲とを算出し、第１の範囲と第２の範囲とを比較し、第１の範囲と第２の範囲とが部分的に重複する場合にループが並列化不可であることを示す警告を出力する。
【００１２】
また、１つの態様では、コンピュータが実行する並列処理方法が提供される。また、１つの態様では、コンピュータに実行させる並列処理プログラムが提供される。
また、１つの態様では、コンピュータに以下の処理を実行させるコンパイルプログラムが提供される。第１のコードの中から、配列の中の第１のインデックスが示す要素を更新する更新処理と配列の中の第２のインデックスが示す要素を参照する参照処理とを含むループであって、第１のインデックスおよび第２のインデックスの少なくとも一方が実行時に値の決まるパラメータに依存するループを検出する。ループが実行される前にループが並列化可能か検査する検査処理が実行されるように、第１のコードを第２のコードに変換する。検査処理は、実行時におけるパラメータの値に基づいて、配列の中の更新処理によって更新される要素の第１の範囲と配列の中の参照処理によって参照される要素の第２の範囲とを算出し、第１の範囲と第２の範囲とを比較し、第１の範囲と第２の範囲とが部分的に重複する場合にループが並列化不可であることを示す警告を出力することを含む。
【発明の効果】
【００１３】
１つの側面では、ループの並列化に関するプログラムの誤りを効率的に検出できる。
【図面の簡単な説明】
【００１４】
【図１】第１の実施の形態の並列計算装置を示す図である。
【図２】第２の実施の形態のコンパイル装置を示す図である。
【図３】第３の実施の形態の情報処理システムを示す図である。
【図４】並列計算装置のハードウェア例を示すブロック図である。
【図５】コンパイル装置のハードウェア例を示すブロック図である。
【図６】ソースコード例を示す第１の図である。
【図７】定義領域と参照領域の関係例を示す第１の図である。
【図８】ソースコード例を示す第２の図である。
【図９】定義領域と参照領域の関係例を示す第２の図である。
【図１０】ソースコード例を示す第３の図である。
【図１１】定義領域と参照領域の関係例を示す第３の図である。
【図１２】ソースコード例を示す第４の図である。
【図１３】ソースコード例を示す第５の図である。
【図１４】定義領域と参照領域の関係例を示す第４の図である。
【図１５】定義領域と参照領域の関係例を示す第５の図である。
【図１６】ソースコード例を示す第６の図である。
【図１７】並列計算装置とコンパイル装置の機能例を示すブロック図である。
【図１８】ライブラリ呼び出しのパラメータ例を示す図である。
【図１９】エラーメッセージの表示例を示す図である。
【図２０】コンパイルの手順例を示すフローチャートである。
【図２１】ループ前検査の手順例を示すフローチャートである。
【図２２】連続・連続間検査の手順例を示すフローチャートである。
【図２３】連続・規則性間検査の手順例を示すフローチャートである。
【図２４】規則性・連続間検査の手順例を示すフローチャートである。
【図２５】規則性・規則性間検査の手順例を示すフローチャートである。
【図２６】ループ内検査の手順例を示すフローチャートである。
【図２７】個別定義検査の手順例を示すフローチャートである。
【図２８】個別参照検査の手順例を示すフローチャートである。
【発明を実施するための形態】
【００１５】
以下、本実施の形態を図面を参照して説明する。
［第１の実施の形態］
第１の実施の形態を説明する。
【００１６】
図１は、第１の実施の形態の並列計算装置を示す図である。
第１の実施の形態の並列計算装置１０は、複数のプロセッサ（プロセッサコアと呼ばれるものを含む）と共有メモリとを有する共有メモリ型マルチプロセッサ装置である。並列計算装置１０は、複数のプロセッサを用いて複数のスレッドを並列に実行することができる。これら複数のスレッドは共有メモリを使用することができる。並列計算装置１０は、ユーザが操作するクライアントコンピュータでもよいし、クライアントコンピュータからアクセスされるサーバコンピュータでもよい。
【００１７】
並列計算装置１０は、記憶部１１および演算部１２を有する。記憶部１１は、ＲＡＭ（Random Access Memory）などの揮発性の半導体メモリでもよいし、ＨＤＤ（Hard Disk Drive）やフラッシュメモリなどの不揮発性のストレージでもよい。記憶部１１は、上記の共有メモリであってもよい。演算部１２は、例えば、ＣＰＵ（Central Processing Unit）、ＣＰＵコア、ＤＳＰ（Digital Signal Processor）などのプロセッサである。演算部１２は、上記の複数のスレッドの１つを実行するプロセッサであってもよい。演算部１２は、例えば、記憶部１１などのメモリに記憶されたプログラムを実行する。実行されるプログラムには、並列処理プログラムが含まれる。
【００１８】
記憶部１１は、コード１３を記憶する。コード１３は、例えば、並列計算装置１０のプロセッサが実行できるようにコンパイルされたオブジェクトコードである。コード１３は、ループ１３ａを含む。ループ１３ａは、配列１３ｂ（配列Ａ）の中のインデックス１３ｃ（第１のインデックス）が示す要素を更新する更新処理を含む。また、ループ１３ａは、配列１３ｂの中のインデックス１３ｄ（第２のインデックス）が示す要素を参照する参照処理を含む。インデックス１３ｃ，１３ｄは「添字」と呼ばれることがある。
【００１９】
インデックス１３ｃ，１３ｄは、ループ１３ａの繰り返しを制御するループ変数に依存する。例えば、インデックス１３ｃ，１３ｄはそれぞれループ変数ｎを含む。また、インデックス１３ｃ，１３ｄの少なくとも一方は、実行時に値の決まるパラメータに依存する。パラメータは、「変数」や「引数」などと呼ばれてもよい。パラメータは、例えば、ループの実行前までに値が決まりループ内では値が不変な変数である。パラメータは、ループ変数の上限値、下限値、増分など、ループ変数の値域を定義するものであってもよい。また、パラメータは、インデックス１３ｃ，１３ｄの少なくとも一方に含まれていてもよい。図１の例では、インデックス１３ｃはパラメータｐ１を含み、インデックス１３ｄはパラメータｐ２を含んでいる。パラメータｐ１，ｐ２の値は実行時に決まるため、インデックス１３ｃ，１３ｄの値域を静的に算出することは難しい。
【００２０】
演算部１２は、記憶部１１に記憶されたコード１３の実行を開始する。演算部１２は、ループ１３ａが実行される直前に、ループ１３ａが並列化可能か判定する検査処理を行う。並列化可能と判定された場合、並列計算装置１０は、複数のプロセッサ（演算部１２を含んでもよい）を用いてループ１３ａの繰り返し処理を並列に実行してもよい。一方、並列化不可と判定された場合、演算部１２は、ループ１３ａが並列化不可であることを示す警告１５を出力する。演算部１２は、例えば、警告１５を示すメッセージを記憶部１１または他の記憶装置にログとして記憶する。また、演算部１２は、例えば、警告１５を示すメッセージを、並列計算装置１０に接続されたディスプレイに表示する。
【００２１】
検査処理では、演算部１２は、実行時におけるパラメータの値に基づいて、範囲１４ａ（第１の範囲）および範囲１４ｂ（第２の範囲）を算出する。範囲１４ａは、配列１３ｂに含まれる複数の要素のうち、ループ１３ａの繰り返し全体を通じて（ループ１３ａの開始から終了までの間に）更新される要素の範囲である。範囲１４ｂは、配列１３ｂに含まれる複数の要素のうち、ループ１３ａの繰り返し全体を通じて参照される要素の範囲である。範囲１４ａ，１４ｂは、配列１３ｂに割り当てられたメモリ上の記憶領域を示すアドレス（メモリアドレス）を用いて表現されてもよい。
【００２２】
例えば、演算部１２は、ループ変数の下限値・上限値・増分（繰り返し処理１回毎に増加するループ変数の値）、配列１３ｂの要素１つ当たりのデータサイズ、その他のパラメータの値などに基づいて、範囲１４ａ，１４ｂを算出する。範囲１４ａ，１４ｂの少なくとも一方は、配列１３ｂに含まれる複数の要素のうちの連続した要素の集合を示すものであってもよく、メモリ上の連続した記憶領域を示すものであってもよい。また、範囲１４ａ，１４ｂの少なくとも一方は、配列１３ｂに含まれる複数の要素のうちの規則的に離れた要素の集合を示すものであってもよく、メモリ上の規則的に離れた記憶領域を示すものであってもよい。複数の要素または複数の記憶領域が規則的に離れているとは、それら要素または記憶領域が所定の間隔を空けて離れている場合を含む。
【００２３】
そして、演算部１２は、算出した範囲１４ａと範囲１４ｂとを比較する。範囲１４ａと範囲１４ｂとが部分的に重複している場合（一部の要素が重複し一部の要素が重複していない場合）、演算部１２は、ループ１３ａが並列化不可であると判定する。すると、演算部１２は、並列化不可であることを示す警告１５を出力する。一方、範囲１４ａと範囲１４ｂとが一致している場合、演算部１２は、ループ１３ａが並列化可能であると判定してもよい。また、範囲１４ａと範囲１４ｂとが重複していない場合（重複する要素が存在しない場合）、演算部１２は、ループ１３ａが並列化可能であると判定してもよい。
【００２４】
なお、演算部１２が実行する上記の検査処理は、ライブラリプログラムとして実装されてもよい。その場合、コンパイラによって、コード１３のループ１３ａの直前に、当該ライブラリプログラムを呼び出す呼び出し命令が挿入されていてもよい。
【００２５】
第１の実施の形態の並列計算装置１０によれば、ループ１３ａが実行される前に、実行時におけるパラメータの値に基づいて、配列１３ｂの中の更新される要素の範囲１４ａと参照される要素の範囲１４ｂとが算出される。そして、ループ１３ａが実行される前に、範囲１４ａと範囲１４ｂとが比較され、範囲１４ａと範囲１４ｂとが部分的に重複する場合にはループ１３ａが並列化不可であることを示す警告１５が出力される。
【００２６】
このように、実行時に値の決まるパラメータが存在する場合であっても、ループ１３ａの実行前にループ１３ａが並列化可能か判定できる。並列化可能と判定された場合には、複数のスレッドを起動してループ１３ａの繰り返し処理を並列に実行することが可能となる。一方、ループ１３ａ内でインデックス１３ｃ，１３ｄの値を検査するようにすると、この検査のためにループ１３ａを並列化することが難しくなる。よって、第１の実施の形態によれば、ループ１３ａの並列化が阻害されなくなり、ループ１３ａの実行時間を短縮することができる。また、多重ループによってインデックス１３ｃの値とインデックス１３ｄの値の具体的な組み合わせを全て算出する方法と比べて、検査処理の負荷を軽減することができる。その結果、ループ１３ａの並列化に関するコード１３の誤りを効率的に検出することができ、コード１３の実行効率が向上する。
【００２７】
［第２の実施の形態］
次に、第２の実施の形態を説明する。
図２は、第２の実施の形態のコンパイル装置を示す図である。
【００２８】
第２の実施の形態のコンパイル装置２０は、第１の実施の形態の並列計算装置１０のような並列処理能力を有するコンピュータに実行させるコードを生成する。コンパイル装置２０は、ソフトウェアとして実装されたコンパイラを実行するこのピュータでもよい。コンパイル装置２０は、ユーザが操作するクライアントコンピュータでもよいし、クライアントコンピュータからアクセスされるサーバコンピュータでもよい。
【００２９】
コンパイル装置２０は、記憶部２１および変換部２２を有する。記憶部２１は、ＲＡＭなどの揮発性の半導体メモリでもよいし、ＨＤＤやフラッシュメモリなどの不揮発性のストレージでもよい。変換部２２は、例えば、ＣＰＵやＤＳＰなどのプロセッサである。変換部２２は、例えば、記憶部２１などのメモリに記憶されたプログラムを実行する。実行されるプログラムには、コンパイルプログラムが含まれる。
【００３０】
記憶部２１は、コード２３（第１のコード）を記憶する。コード２３は、ユーザが作成したソースコードでもよいし、ソースコードから変換された中間コードでもよいし、ソースコードまたは中間コードから変換されたオブジェクトコードでもよい。また、記憶部２１は、コード２３から変換されるコード２４（第２のコード）を記憶する。コード２４は、ソースコードでもよいし中間コードでもよいしオブジェクトコードでもよい。なお、コード２３，２４は、「プログラム」や「命令の集合」などと呼ぶことも可能である。
【００３１】
コード２３は、ループ２３ａを含む。ループ２３ａは、配列２３ｂの中のインデックス２３ｃ（第１のインデックス）が示す要素を更新する更新処理を含む。また、ループ２３ａは、配列２３ｂの中のインデックス２３ｄ（第２のインデックス）が示す要素を参照する参照処理を含む。インデックス２３ｃ，２３ｄの少なくとも一方は、実行時に値の決まるパラメータに依存する。ループ２３ａは、第１の実施の形態のループ１３ａに対応する。配列２３ｂは、第１の実施の形態の配列１３ｂに対応する。インデックス２３ｃ，２３ｄは、第１の実施の形態のインデックス１３ｃ，１３ｄに対応する。
【００３２】
コード２４は、ループ２３ａが並列化可能か否か検査する機能を有する。コード２４は、「デバッグ用のコード」と言うこともできる。コンパイル装置２０は、ユーザから入力されたコンパイルコマンドに所定のオプション（例えば、デバッグオプション）が付加されている場合のみ、コード２３をコード２４に変換するようにしてもよい。
【００３３】
変換部２２は、コード２３からループ２３ａを検出する。検出するループ２３ａは、ユーザによって並列化が指示されたループであってもよい。変換部２２は、ループ２３ａから配列２３ｂの更新の命令と配列２３ｂの参照の命令を抽出する。インデックス２３ｃ，２３ｄの少なくとも一方がパラメータに依存するため、ループ２３ａの繰り返し全体を通じて（ループ２３ａの開始から終了までの間に）同じ要素が更新されかつ参照されるかを静的に判定することが難しい。そこで、変換部２２は、ループ２３ａの直前に検査処理２４ａが実行されるようにコード２３からコード２４を生成する。例えば、変換部２２は、ループ２３ａの直前に検査用の命令を挿入する。また、例えば、変換部２２は、ループ２３ａの直前に、検査用のライブラリを呼び出す呼び出し命令を挿入する。
【００３４】
検査処理２４ａは、実行時におけるパラメータの値に基づいて、配列２３ｂの中の更新される要素の範囲２４ｂ（第１の範囲）と配列２３ｂの中の参照される要素の範囲２４ｃ（第２の範囲）とを算出することを含む。範囲２４ｂ，２４ｃは、第１の実施の形態の範囲１４ａ，１４ｂに対応する。また、検査処理２４ａは、範囲２４ｂと範囲２４ｃとを比較し、両者が部分的に重複する場合にループ２３ａが並列化不可であることを示す警告２５を出力することを含む。警告２５は、第１の実施の形態の警告１５に対応する。
【００３５】
第２の実施の形態のコンパイル装置２０によれば、コード２３からループ２３ａが検出され、ループ２３ａの実行前にループ２３ａが並列化可能か検査する検査処理２４ａが実行されるように、コード２３がコード２４に変換される。検査処理２４ａでは、実行時のパラメータの値に基づいて、更新される範囲２４ｂと参照される範囲２４ｃとが算出され、範囲２４ｂ，２４ｃが部分的に重複する場合に警告２５が出力される。
【００３６】
これにより、コンパイル時にループ２３ａの並列化可否を静的に判定することが難しい場合であっても、実行時にループ２３ａの並列化可否を動的に判定するコード２４を生成することができる。また、並列化可能と判定された場合には、ループ２３ａの繰り返し処理を並列に実行することが可能となる。よって、ループ２３ａの並列化が阻害されなくなり、ループ２３ａの実行時間を短縮することができる。また、ループ２３ａの実行前に検査処理２４ａが実行されるため、検査の負荷を軽減することができる。その結果、ループ２３ａの並列化に関するコード２３の誤りを効率的に検出できるようになる。
【００３７】
［第３の実施の形態］
次に、第３の実施の形態を説明する。
図３は、第３の実施の形態の情報処理システムを示す図である。
【００３８】
第３の実施の形態の情報処理システムは、並列計算装置１００およびコンパイル装置２００を有する。並列計算装置１００とコンパイル装置２００とは、ネットワーク３０を介して接続されている。並列計算装置１００およびコンパイル装置２００はそれぞれ、ユーザが操作するクライアントコンピュータでもよいし、ネットワーク３０を介してクライアントコンピュータからアクセスされるサーバコンピュータでもよい。なお、並列計算装置１００は、第１の実施の形態の並列計算装置１０に対応する。コンパイル装置２００は、第２の実施の形態のコンパイル装置２０に対応する。
【００３９】
並列計算装置１００は、複数のＣＰＵコアを用いて複数のスレッドを並列に実行することができる共有メモリ型マルチプロセッサ装置である。コンパイル装置２００は、ユーザが作成したソースコードを、並列計算装置１００が実行可能なオブジェクトコードに変換する。その際、コンパイル装置２００は、ソースコードから、並列に動作する複数のスレッドを起動可能な並列処理用のオブジェクトコードを生成することができる。生成されたオブジェクトコードは、コンパイル装置２００から並列計算装置１００に送信される。ただし、第３の実施の形態ではプログラムをコンパイルする装置と実行する装置とを別装置としたが、両者が同一装置であってもよい。
【００４０】
図４は、並列計算装置のハードウェア例を示すブロック図である。
並列計算装置１００は、ＣＰＵ１０１、ＲＡＭ１０２、ＨＤＤ１０３、画像信号処理部１０４、入力信号処理部１０５、媒体リーダ１０６および通信インタフェース１０７を有する。上記ユニットはバス１０８に接続される。
【００４１】
ＣＰＵ１０１は、プログラムの命令を実行するプロセッサである。ＣＰＵ１０１は、ＨＤＤ１０３に記憶されたプログラムやデータの少なくとも一部をＲＡＭ１０２にロードし、プログラムを実行する。ＣＰＵ１０１は、ＣＰＵコア１０１ａ〜１０１ｄを有する。ＣＰＵコア１０１ａ〜１０１ｄは、並列にスレッドを実行することができる。ただし、ＣＰＵ１０１が有するＣＰＵコアの数は、２以上の任意の数でよい。なお、ＣＰＵ１０１ａ〜１０１ｄそれぞれを「プロセッサ」と呼ぶこともあるし、ＣＰＵ１０１ａ〜１０１ｄの集合またはＣＰＵ１０１を「プロセッサ」と呼ぶこともある。
【００４２】
ＲＡＭ１０２は、ＣＰＵ１０１が実行するプログラムやＣＰＵ１０１が演算に用いるデータを一時的に記憶する揮発性の半導体メモリである。なお、並列計算装置１００は、ＲＡＭ以外の種類のメモリを備えてもよく、複数個のメモリを備えてもよい。
【００４３】
ＨＤＤ１０３は、ＯＳ（Operating System）やミドルウェアやアプリケーションソフトウェアなどのソフトウェアのプログラム、および、データを記憶する不揮発性の記憶装置である。プログラムには、コンパイル装置２００によってコンパイルされたものが含まれる。なお、並列計算装置１００は、フラッシュメモリやＳＳＤ（Solid State Drive）などの他の種類の記憶装置を備えてもよく、複数の不揮発性の記憶装置を備えてもよい。
【００４４】
画像信号処理部１０４は、ＣＰＵ１０１からの命令に従って、並列計算装置１００に接続されたディスプレイ１１１に画像を出力する。ディスプレイ１１１としては、ＣＲＴ（Cathode Ray Tube）ディスプレイ、液晶ディスプレイ（ＬＣＤ：Liquid Crystal Display）、プラズマディスプレイ（ＰＤＰ：Plasma Display Panel）、有機ＥＬ（ＯＥＬ：Organic Electro-Luminescence）ディスプレイなどを用いることができる。
【００４５】
入力信号処理部１０５は、並列計算装置１００に接続された入力デバイス１１２から入力信号を取得し、ＣＰＵ１０１に出力する。入力デバイス１１２としては、マウスやタッチパネルやタッチパッドやトラックボールなどのポインティングデバイス、キーボード、リモートコントローラ、ボタンスイッチなどを用いることができる。また、並列計算装置１００に、複数の種類の入力デバイスが接続されていてもよい。
【００４６】
媒体リーダ１０６は、記録媒体１１３に記録されたプログラムやデータを読み取る読み取り装置である。記録媒体１１３として、例えば、フレキシブルディスク（ＦＤ：Flexible Disk）やＨＤＤなどの磁気ディスク、ＣＤ（Compact Disc）やＤＶＤ（Digital Versatile Disc）などの光ディスク、光磁気ディスク（ＭＯ：Magneto-Optical disk）、半導体メモリなどを使用できる。媒体リーダ１０６は、例えば、記録媒体１１３から読み取ったプログラムやデータをＲＡＭ１０２またはＨＤＤ１０３に格納する。
【００４７】
通信インタフェース１０７は、ネットワーク３０に接続され、ネットワーク３０を介してコンパイル装置２００などの他の装置と通信を行うインタフェースである。通信インタフェース１０７は、スイッチなどの通信装置とケーブルで接続される有線通信インタフェースでもよいし、基地局と無線リンクで接続される無線通信インタフェースでもよい。
【００４８】
なお、並列計算装置１００は、媒体リーダ１０６を備えていなくてもよく、ユーザが操作する端末装置から制御可能である場合には画像信号処理部１０４や入力信号処理部１０５を備えていなくてもよい。また、ディスプレイ１１１や入力デバイス１１２が、並列計算装置１００の筐体と一体に形成されてもよい。ＣＰＵ１０１は、第１の実施の形態の演算部１２に対応する。ＲＡＭ１０２は、第１の実施の形態の記憶部１１に対応する。
【００４９】
図５は、コンパイル装置のハードウェア例を示すブロック図である。
コンパイル装置２００は、ＣＰＵ２０１、ＲＡＭ２０２、ＨＤＤ２０３、画像信号処理部２０４、入力信号処理部２０５、媒体リーダ２０６および通信インタフェース２０７を有する。上記ユニットはバス２０８に接続される。
【００５０】
ＣＰＵ２０１は、並列計算装置１００のＣＰＵ１０１と同様の機能を有する。ただし、ＣＰＵ２０１が有するＣＰＵコアの数は１つであってもよく、ＣＰＵ２０１はマルチプロセッサでなくてもよい。ＲＡＭ２０２は、並列計算装置１００のＲＡＭ１０２と同様の機能を有する。ＨＤＤ２０３は、並列計算装置１００のＨＤＤ１０３と同様の機能を有する。ただし、ＨＤＤ２０３が記憶するプログラムには、コンパイルプログラムが含まれる。
【００５１】
画像信号処理部２０４は、並列計算装置１００の画像信号処理部１０４と同様の機能を有する。画像信号処理部２０４は、コンパイル装置２００に接続されたディスプレイ２１１に画像を出力する。入力信号処理部２０５は、並列計算装置１００の入力信号処理部１０５と同様の機能を有する。入力信号処理部２０５は、コンパイル装置２００に接続された入力デバイス２１２から入力信号を取得する。
【００５２】
媒体リーダ２０６は、並列計算装置１００の媒体リーダ１０６と同様の機能を有する。媒体リーダ２０６は、記録媒体２１３に記録されたプログラムやデータを読み取る。ただし、記録媒体１１３と記録媒体２１３とが同一媒体であってもよい。通信インタフェース２０７は、並列計算装置１００の通信インタフェース１０７と同様の機能を有する。通信インタフェース２０７は、ネットワーク３０に接続されている。
【００５３】
なお、コンパイル装置２００は、媒体リーダ２０６を備えていなくてもよく、ユーザが操作する端末装置から制御可能である場合には画像信号処理部２０４や入力信号処理部２０５を備えていなくてもよい。また、ディスプレイ２１１や入力デバイス２１２が、コンパイル装置２００の筐体と一体に形成されてもよい。ＣＰＵ２０１は、第２の実施の形態の変換部２２に対応する。ＲＡＭ１０２は、第２の実施の形態の記憶部２１に対応する。
【００５４】
次に、ループの並列化の可否について説明する。
ユーザが作成するソースコードには、複数のスレッドを用いてループの繰り返し処理を並列実行することを示す並列化指示文が記載されていることがある。第３の実施の形態では主に、プログラミング言語の仕様の中に並列化指示文が規定されている場合を考える。ソースコードに並列化指示文が記載されていると、コンパイル装置２００は、原則としてユーザの指示に従い、ループの繰り返し処理を並列実行するオブジェクトコードを生成する。すなわち、繰り返し処理のうちのｉ回目の処理とｊ回目の処理（ｉ，ｊは異なる正の整数）が、異なるＣＰＵコア上で動作する異なるスレッドによって実行される。
【００５５】
ただし、ループ内で、配列に値を格納すること（「定義」）と当該配列から値を取得すること（「参照」）の両方が行われる場合、ｉ回目の処理とｊ回目の処理との間に依存関係が生じることがある。依存関係は、ｉ回目の処理で定義される配列の要素と、ｊ回目の処理で参照される配列の要素とが同一である場合に発生する。繰り返し処理に依存関係のあるループを並列化すると、実行順序が保証されないために処理結果が不定になってしまう。このため、繰り返し処理に依存関係のあるループに対して並列化指示文が記載されたソースコードは、意味的な誤りのあるソースコードであると言うことができる。
【００５６】
繰り返し処理に依存関係があるか否かは、定義に使用されるインデックス（配列の添字）の値域と参照に使用されるインデックスの値域との間の関係による。ループの繰り返しを制御するループ変数の下限値・上限値・増分が定数であり、２つのインデックスが共にループ変数のみに依存する場合、コンパイル装置２００は、コンパイル時に静的に２つのインデックスの値域を特定することができる。この場合、コンパイル装置２００は、コンパイル時に静的にループの並列化可否を判定することが可能である。
【００５７】
配列を格納するメモリ領域のうち、ループの繰り返し処理全体を通じて定義される領域（定義領域）と、ループの繰り返し処理全体を通じて参照される領域（参照領域）とが比較される。定義領域と参照領域とが完全一致する場合、ｉ回目の処理内で定義と参照の間に依存関係が生じる可能性はあるものの、ｉ回目の処理とｊ回目の処理との間に依存関係が生じる可能性は低い。このため、完全一致の場合は並列化可能と判定できる。また、定義領域と参照領域とが重複しない場合、並列化可能と判定できる。一方、定義領域と参照領域とが一部重複する場合、ある領域がｉ回目の処理において定義されｊ回目の処理において参照される可能性が高い。このため、一部重複の場合は並列化不可と判定できる。
【００５８】
このように、配列の定義に使用するインデックスと参照に使用するインデックスとがループ変数以外の変数に依存しない場合、ループの並列化可否をコンパイル時に静的に判定できる。これに対し、配列の定義に使用するインデックスと参照に使用するインデックスとがループ変数以外の変数に依存する場合、ループの並列化可否をコンパイル時に静的に判定することは難しい。ループ変数以外の変数は、ループ変数の下限値、上限値または増分を示すことがある。また、ループ変数以外の変数は、インデックスに含まれることがある。ループ変数以外の変数は、通常、ループの実行前に値が決定されてループ内では不変である。この場合、コンパイル装置２００は、ループの並列化可否を実行時に動的に判定するデバッグ用のオブジェクトコードを生成する。デバッグ用のオブジェクトコードは、コンパイルコマンドにデバッグオプションが付加された場合のみ生成される。
【００５９】
以下、定義領域と参照領域とを比較する例を説明する。
図６は、ソースコード例を示す第１の図である。
ソースコード４１には、サブルーチンｆｏｏ１が記載されている。サブルーチンｆｏｏ１は、引数としてｋ１，ｋ２，ｉｎを取得する。サブルーチンｆｏｏ１は、長さがｋ２＋１の実数型の配列ａを定義する。サブルーチンｆｏｏ１は、ループ変数ｎの値をｋ１からｋ２まで１ずつ増加させながらループを実行する。このループは、並列化指示文「ＣＯＮＣＵＲＲＥＮＴ」によって並列に実行するよう指示されている。ループは、配列ａのｎ＋ｉｎ番目の要素の定義と、配列ａのｎ番目の要素の参照とを含む。配列ａの定義領域および参照領域は、実行時に値が決まる引数ｋ１，ｋ２，ｉｎに依存することになる。ソースコード４１には、引数としてｋ１＝１，ｋ２＝１０００，ｉｎ＝１を指定してサブルーチンｆｏｏ１を呼び出す呼び出し文が記載されている。
【００６０】
ソースコード４２には、サブルーチンｆｏｏ２が記載されている。サブルーチンｆｏｏ２は、引数としてｋ１，ｋ２，ｋ３，ｋ４を取得する。サブルーチンｆｏｏ２は、ループ変数ｎの値をｋ１からｋ２まで１ずつ増加させながらループを実行する。ループは、配列ａのｎ＋ｋ３番目の要素の定義と、配列ａのｎ＋ｋ４番目の要素の参照とを含む。配列ａの定義領域および参照領域は、実行時に値が決まる引数ｋ１，ｋ２，ｋ３，ｋ４に依存することになる。ソースコード４２には、引数としてｋ１＝１，ｋ２＝１０００，ｋ３＝０，ｋ４＝０を指定してサブルーチンｆｏｏ２を呼び出す呼び出し文が記載されている。
【００６１】
ソースコード４３には、サブルーチンｆｏｏ３が記載されている。サブルーチンｆｏｏ３は、引数としてｋ１，ｋ２を取得する。サブルーチンｆｏｏ３は、ループ変数ｎの値をｋ１からｋ２まで１ずつ増加させながらループを実行する。ループは、配列ａのｎ＋１０００番目の要素の定義と、配列ａのｎ番目の要素の参照とを含む。配列ａの定義領域および参照領域は、実行時に値が決まる引数ｋ１，ｋ２に依存することになる。ソースコード４３には、引数としてｋ１＝１，ｋ２＝１０００を指定してサブルーチンｆｏｏ３を呼び出す呼び出し文が記載されている。
【００６２】
図７は、定義領域と参照領域の関係例を示す第１の図である。
定義領域６１ａは、ソースコード４１のループに基づいて定義される領域である。具体的には、定義領域６１ａは、ａ（２）からａ（１００１）までの連続した領域である。参照領域６１ｂは、ソースコード４１のループに基づいて参照される領域である。具体的には、参照領域６１ｂは、ａ（１）からａ（１０００）までの連続した領域である。定義領域６１ａと参照領域６１ｂとを比較すると、ａ（２）からａ（１０００）までが重複している一方、ａ（１）とａ（１００１）は重複していない。すなわち、定義領域６１ａと参照領域６１ｂとは一部重複している。このため、ソースコード４１のループは並列化不可であり、ソースコード４１は意味的な誤りを有している。
【００６３】
定義領域６２ａは、ソースコード４２のループに基づいて定義される領域である。具体的には、定義領域６２ａは、ａ（１）からａ（１０００）までの連続した領域である。参照領域６２ｂは、ソースコード４２のループに基づいて参照される領域である。具体的には、参照領域６２ｂは、ａ（１）からａ（１０００）までの連続した領域である。定義領域６２ａと参照領域６２ｂとを比較すると、両者は完全一致している。このため、ソースコード４２のループは並列化可能であり、ソースコード４２に意味的な誤りはない。
【００６４】
定義領域６３ａは、ソースコード４３のループに基づいて定義される領域である。具体的には、定義領域６３ａは、ａ（１００１）からａ（２０００）までの連続した領域である。参照領域６３ｂは、ソースコード４３のループに基づいて参照される領域である。具体的には、参照領域６３ｂは、ａ（１）からａ（１０００）までの連続した領域である。定義領域６３ａと参照領域６３ｂとを比較すると、両者は重複しない。このため、ソースコード４３のループは並列化可能であり、ソースコード４３に意味的な誤りはない。
【００６５】
ここで、定義領域６１ａと参照領域６１ｂは、引数ｋ１，ｋ２，ｉｎから算出できる。このため、並列計算装置１００は、ループの実行前に、定義領域６１ａと参照領域６１ｂを算出して並列化不可であることを判定できる。同様に、定義領域６２ａと参照領域６２ｂは、引数ｋ１，ｋ２，ｋ３，ｋ４から算出できる。このため、並列計算装置１００は、ループの実行前に、定義領域６２ａと参照領域６２ｂを算出して並列化可能であることを判定できる。また、定義領域６３ａと参照領域６３ｂは、引数ｋ１，ｋ２から算出できる。このため、並列計算装置１００は、ループの実行前に、定義領域６３ａと参照領域６３ｂを算出して並列化可能であることを判定できる。このように、定義領域と参照領域が連続領域である場合、ループの実行前に並列化可否を判定できる。
【００６６】
図８は、ソースコード例を示す第２の図である。
ソースコード４４には、サブルーチンｆｏｏ４が記載されている。サブルーチンｆｏｏ４は、引数としてｋを取得する。サブルーチンｆｏｏ４は、大きさが１０００×１０００の実数型の二次元配列ａを定義する。サブルーチンｆｏｏ４は、ループ変数ｎの値を１から９９９まで１ずつ増加させながらループを実行する。ループは、二次元配列ａの（１，ｎ）〜（１０００，ｎ）の範囲の要素の定義を含む。また、ループは、二次元配列ａの（１，ｎ＋１）〜（１０００，ｎ＋１）の範囲の要素の参照を含む。ただし、参照される要素はｋ個に１個の割合で選択される。二次元配列ａの参照領域は、実行時に値が決まる引数ｋに依存することになる。ソースコード４４には、引数としてｋ＝２を指定してサブルーチンｆｏｏ４を呼び出す呼び出し文が記載されている。
【００６７】
ソースコード４５には、サブルーチンｆｏｏ５が記載されている。サブルーチンｆｏｏ５は、引数としてｋを取得する。サブルーチンｆｏｏ５は、ループ変数ｎの値を１から１０００まで１ずつ増加させながらループを実行する。ループは、二次元配列ａの（１，ｎ）〜（１０００，ｎ）の範囲の要素の定義を含む。また、ループは、二次元配列ａの（１，ｎ）〜（１０００，ｎ）の範囲の要素の参照を含む。ただし、参照される要素はｋ個に１個の割合で選択される。二次元配列ａの参照領域は、実行時に値が決まる引数ｋに依存することになる。ソースコード４５には、引数としてｋ＝１を指定してサブルーチンｆｏｏ５を呼び出す呼び出し文が記載されている。
【００６８】
ソースコード４６には、サブルーチンｆｏｏ６が記載されている。サブルーチンｆｏｏ６は、引数としてｋ１，ｋ２を取得する。サブルーチンｆｏｏ６は、ループ変数ｎの値をｋ１＋１からｋ２−１まで１ずつ増加させながらループを実行する。ループは、二次元配列ａの（ｎ，１）の要素の定義と、二次元配列ａの（１，ｎ）の要素の参照とを含む。二次元配列ａの定義領域および参照領域は、実行時に値が決まる引数ｋ１，ｋ２に依存することになる。ソースコード４６には、引数としてｋ１＝１，ｋ２＝１０００を指定してサブルーチンｆｏｏ６を呼び出す呼び出し文が記載されている。
【００６９】
図９は、定義領域と参照領域の関係例を示す第２の図である。
二次元配列の要素については、メモリ上に（１，１），（２，１），…，（１０００，１），（１，２），（２，２），…，（１０００，２），…のような順序で配置されるものとする。すなわち、二次元目のインデックスの値が同じで一次元目のインデックスの値が異なる要素が、連続したメモリ領域に配置されるものとする。
【００７０】
定義領域６４ａは、ソースコード４４のループに基づいて定義される領域である。具体的には、定義領域６４ａは、ａ（１，１）からａ（１０００，９９９）までの連続した領域である。参照領域６４ｂは、ソースコード４４のループに基づいて参照される領域である。具体的には、参照領域６４ｂは、ａ（１，２），ａ（３，２），…，ａ（９９９，９９９），…，ａ（９９９，１０００）のように規則的に間隔の空いた領域である。定義領域６４ａと参照領域６４ｂとを比較すると、参照領域６４ｂのａ（１，２），…，ａ（９９９，９９９）が定義領域６４ａと重複している。一方、参照領域６４ｂのａ（１，１０００），…，ａ（９９９，１０００）は定義領域６４ａと重複していない。すなわち、定義領域６４ａと参照領域６４ｂとは一部重複している。このため、ソースコード４４のループは並列化不可であり、ソースコード４４は意味的な誤りを有している。
【００７１】
定義領域６５ａは、ソースコード４５のループに基づいて定義される領域である。具体的には、定義領域６５ａは、ａ（１，１）からａ（１０００，１０００）までの連続した領域である。参照領域６５ｂは、ソースコード４５のループに基づいて参照される領域である。具体的には、参照領域６５ｂは、ａ（１，１）からａ（１０００，１０００）までの連続した領域である。引数ｋの値が１であるため、参照領域６４ｂとは異なり、参照領域６５ｂは実質的に、間隔の空いた領域ではなく連続した領域になっている。定義領域６５ａと参照領域６５ｂとを比較すると、両者は完全一致している。このため、ソースコード４５のループは並列化可能であり、ソースコード４５に意味的な誤りはない。
【００７２】
定義領域６６ａは、ソースコード４６のループに基づいて定義される領域である。具体的には、定義領域６６ａは、ａ（２，１）からａ（９９９，１）までの連続した領域である。参照領域６６ｂは、ソースコード４６のループに基づいて参照される領域である。具体的には、参照領域６６ｂは、ａ（１，２），ａ（１，３），…，ａ（１，９９９）のように規則的に間隔の空いた領域である。定義領域６６ａと参照領域６６ｂとを比較すると、両者は重複しない。このため、ソースコード４６のループは並列化可能であり、ソースコード４６に意味的な誤りはない。
【００７３】
ここで、定義領域６４ａは静的に算出でき、参照領域６４ｂは引数ｋから算出できる。このため、並列計算装置１００は、ループの実行前に、定義領域６４ａと参照領域６４ｂを算出して並列化不可であることを判定できる。同様に、定義領域６５ａは静的に算出でき、参照領域６５ｂは引数ｋから算出できる。このため、並列計算装置１００は、ループの実行前に、定義領域６５ａと参照領域６５ｂを算出して並列化可能であることを判定できる。また、定義領域６６ａと参照領域６６ｂは、引数ｋ１，ｋ２から算出できる。このため、並列計算装置１００は、ループの実行前に、定義領域６６ａと参照領域６６ｂを算出して並列化可能であることを判定できる。このように、定義領域が連続領域であり参照領域が規則的領域である場合、ループの実行前に並列化可否を判定できる。
【００７４】
なお、参照領域６５ｂは連続した領域になっているものの、コンパイル時には引数ｋの値が不明であるため、ソースコード４５からは参照領域６５ｂが規則的領域になると仮定してオブジェクトコードが生成される。
【００７５】
図１０は、ソースコード例を示す第３の図である。
ソースコード４７には、サブルーチンｆｏｏ７が記載されている。サブルーチンｆｏｏ７は、引数としてｋを取得する。サブルーチンｆｏｏ７は、大きさが１０００×１０００の実数型の二次元配列ａを定義する。サブルーチンｆｏｏ７は、ループ変数ｎの値を１から９９９まで１ずつ増加させながらループを実行する。ループは、二次元配列ａの（１，ｎ＋１）〜（１０００，ｎ＋１）の範囲の要素の定義を含む。ただし、定義される要素はｋ個に１個の割合で選択される。また、ループは、二次元配列ａの（１，ｎ）〜（１０００，ｎ）の範囲の要素の参照を含む。二次元配列ａの定義領域は、実行時に値が決まる引数ｋに依存することになる。ソースコード４７には、引数としてｋ＝２を指定してサブルーチンｆｏｏ７を呼び出す呼び出し文が記載されている。
【００７６】
ソースコード４８には、サブルーチンｆｏｏ８が記載されている。サブルーチンｆｏｏ８は、引数としてｋを取得する。サブルーチンｆｏｏ８は、ループ変数ｎの値を１から１０００まで１ずつ増加させながらループを実行する。ループは、二次元配列ａの（１，ｎ）〜（１０００，ｎ）の範囲の要素の定義を含む。ただし、定義される要素はｋ個に１個の割合で選択される。また、ループは、二次元配列ａの（１，ｎ）〜（１０００，ｎ）の範囲の要素の参照を含む。二次元配列ａの定義領域は、実行時に値が決まる引数ｋに依存することになる。ソースコード４８には、引数としてｋ＝１を指定してサブルーチンｆｏｏ８を呼び出す呼び出し文が記載されている。
【００７７】
ソースコード４９には、サブルーチンｆｏｏ９が記載されている。サブルーチンｆｏｏ９は、引数としてｋ１，ｋ２を取得する。サブルーチンｆｏｏ９は、ループ変数ｎの値をｋ１＋１からｋ２−１まで１ずつ増加させながらループを実行する。ループは、二次元配列ａの（１，ｎ）の要素の定義と、二次元配列ａの（ｎ，１）の要素の参照とを含む。二次元配列ａの定義領域および参照領域は、実行時に値が決まる引数ｋ１，ｋ２に依存することになる。ソースコード４９には、引数としてｋ１＝１，ｋ２＝１０００を指定してサブルーチンｆｏｏ９を呼び出す呼び出し文が記載されている。
【００７８】
図１１は、定義領域と参照領域の関係例を示す第３の図である。
定義領域６７ａは、ソースコード４７のループに基づいて定義される領域である。具体的には、定義領域６７ａは、ａ（１，２），ａ（３，２），…，ａ（９９９，９９９），…，ａ（９９９，１０００）のように規則的に間隔の空いた領域である。参照領域６７ｂは、ソースコード４７のループに基づいて参照される領域である。具体的には、参照領域６７ｂは、ａ（１，１）からａ（１０００，９９９）までの連続した領域である。定義領域６７ａと参照領域６７ｂとを比較すると、定義領域６７ａのａ（１，２），…，ａ（９９９，９９９）が参照領域６７ｂと重複している。一方、定義領域６７ａのａ（１，１０００），…，ａ（９９９，１０００）は参照領域６７ｂと重複していない。すなわち、定義領域６７ａと参照領域６７ｂとは一部重複している。このため、ソースコード４７のループは並列化不可であり、ソースコード４７は意味的な誤りを有している。
【００７９】
定義領域６８ａは、ソースコード４８のループに基づいて定義される領域である。具体的には、定義領域６８ａは、ａ（１，１）からａ（１０００，１０００）までの連続した領域である。参照領域６８ｂは、ソースコード４８のループに基づいて参照される領域である。具体的には、参照領域６８ｂは、ａ（１，１）からａ（１０００，１０００）までの連続した領域である。引数ｋの値が１であるため、定義領域６７ａとは異なり、定義領域６８ａは実質的に、間隔の空いた領域ではなく連続した領域になっている。定義領域６８ａと参照領域６８ｂとを比較すると、両者は完全一致している。このため、ソースコード４８のループは並列化可能であり、ソースコード４８に意味的な誤りはない。
【００８０】
定義領域６９ａは、ソースコード４９のループに基づいて定義される領域である。具体的には、定義領域６９ａは、ａ（１，２），ａ（１，３），…，ａ（１，９９９）のように規則的に間隔の空いた領域である。参照領域６９ｂは、ソースコード４９のループに基づいて参照される領域である。参照領域６９ｂは、ａ（２，１）からａ（９９９，１）までの連続した領域である。定義領域６９ａと参照領域６９ｂとを比較すると、両者は重複しない。このため、ソースコード４９のループは並列化可能であり、ソースコード４９に意味的な誤りはない。
【００８１】
ここで、定義領域６７ａは引数ｋから算出でき、参照領域６７ｂは静的に算出できる。このため、並列計算装置１００は、ループの実行前に、定義領域６７ａと参照領域６７ｂを算出して並列化不可であることを判定できる。同様に、定義領域６８ａは引数ｋから算出でき、参照領域６８ｂは引数ｋから算出できる。このため、並列計算装置１００は、ループの実行前に、定義領域６８ａと参照領域６８ｂを算出して並列化可能であることを判定できる。また、定義領域６９ａと参照領域６９ｂは、引数ｋ１，ｋ２から算出できる。このため、並列計算装置１００は、ループの実行前に、定義領域６９ａと参照領域６９ｂを算出して並列化可能であることを判定できる。このように、定義領域が規則的領域であり参照領域が連続領域である場合、ループの実行前に並列化可否を判定できる。
【００８２】
なお、定義領域６８ａは連続した領域になっているものの、コンパイル時には引数ｋの値が不明であるため、ソースコード４８からは定義領域６８ａが規則的領域になると仮定してオブジェクトコードが生成される。
【００８３】
図１２は、ソースコード例を示す第４の図である。
ソースコード５１には、サブルーチンｆｏｏ１１が記載されている。サブルーチンｆｏｏ１１は、引数としてｋ１，ｋ２，ｉｎを取得する。サブルーチンｆｏｏ１１は、ループ変数ｎの値をｋ１からｋ２まで２ずつ増加させながらループを実行する。ループは、配列ａのｎ＋ｉｎ＋１番目の要素の定義と、配列ａのｎ番目の要素の参照とを含む。配列ａの定義領域および参照領域は、実行時に値が決まる引数ｋ１，ｋ２，ｉｎに依存することになる。ソースコード５１には、引数としてｋ１＝１，ｋ２＝１０００，ｉｎ＝１を指定してサブルーチンｆｏｏ１１を呼び出す呼び出し文が記載されている。
【００８４】
ソースコード５２には、サブルーチンｆｏｏ１２が記載されている。サブルーチンｆｏｏ１２は、引数としてｋ１，ｋ２，ｋ３，ｋ４を取得する。サブルーチンｆｏｏ１２は、ループ変数ｎの値をｋ１からｋ２まで２ずつ増加させながらループを実行する。ループは、配列ａのｎ＋ｋ３番目の要素の定義と、配列ａのｎ＋ｋ４番目の要素の参照とを含む。定義領域および参照領域は、実行時に値が決まる引数ｋ１，ｋ２，ｋ３，ｋ４に依存することになる。ソースコード５２には、引数としてｋ１＝１，ｋ２＝１０００，ｋ３＝０，ｋ４＝０を指定してサブルーチンｆｏｏ１２を呼び出す呼び出し文が記載されている。
【００８５】
図１３は、ソースコード例を示す第５の図である。
ソースコード５３には、サブルーチンｆｏｏ１３が記載されている。サブルーチンｆｏｏ１３は、引数としてｋ１，ｋ２を取得する。サブルーチンｆｏｏ１３は、ループ変数ｎの値をｋ１からｋ２まで２ずつ増加させながらループを実行する。ループは、配列ａのｎ番目の要素の定義と、配列ａのｎ＋１０００番目の要素の参照とを含む。配列ａの定義領域および参照領域は、実行時に値が決まる引数ｋ１，ｋ２に依存することになる。ソースコード５３には、引数としてｋ１＝１，ｋ２＝１０００を指定してサブルーチンｆｏｏ１３を呼び出す呼び出し文が記載されている。
【００８６】
ソースコード５４には、サブルーチンｆｏｏ１４が記載されている。サブルーチンｆｏｏ１４は、引数としてｋ１，ｋ２，ｉｎを取得する。サブルーチンｆｏｏ１４は、ループ変数ｎの値をｋ１からｋ２まで２ずつ増加させながらループを実行する。ループは、配列ａのｎ＋ｉｎ番目の要素の定義と、配列ａのｎ番目の要素の参照とを含む。配列ａの定義領域および参照領域は、実行時に値が決まる引数ｋ１，ｋ２，ｉｎに依存することになる。ソースコード５４には、引数としてｋ１＝１，ｋ２＝１０００，ｉｎ＝１を指定してサブルーチンｆｏｏ１４を呼び出す呼び出し文が記載されている。
【００８７】
図１４は、定義領域と参照領域の関係例を示す第４の図である。
定義領域７１ａは、ソースコード５１のループに基づいて定義される領域である。具体的には、定義領域７１ａは、ａ（３），ａ（５），…，ａ（９９９），ａ（１００１）のように規則的に間隔の空いた領域である。参照領域７１ｂは、ソースコード５１のループに基づいて参照される領域である。具体的には、参照領域７１ｂは、ａ（１），ａ（３），ａ（５），…，ａ（９９９）のように規則的に間隔の空いた領域である。定義領域７１ａと参照領域７１ｂとを比較すると、ａ（３），ａ（５），…，ａ（９９９）が重複している一方、ａ（１）とａ（１００１）は重複していない。すなわち、定義領域７１ａと参照領域７１ｂとは一部重複している。このため、ソースコード５１のループは並列化不可であり、ソースコード５１は意味的な誤りを有している。
【００８８】
定義領域７２ａは、ソースコード５２のループに基づいて定義される領域である。具体的には、定義領域７２ａは、ａ（１），ａ（３），…，ａ（９９９）のように規則的に間隔の空いた領域である。参照領域７２ｂは、ソースコード５２のループに基づいて参照される領域である。具体的には、参照領域７２ｂは、ａ（１），ａ（３），…，ａ（９９９）のように規則的に間隔の空いた領域である。定義領域７２ａと参照領域７２ｂとを比較すると、両者は完全一致している。このため、ソースコード５２のループは並列化可能であり、ソースコード５２に意味的な誤りはない。
【００８９】
図１５は、定義領域と参照領域の関係例を示す第５の図である。
定義領域７３ａは、ソースコード５３のループに基づいて定義される領域である。具体的には、定義領域７３ａは、ａ（１００１），ａ（１００３），…，ａ（１９９９）のように規則的に間隔の空いた領域である。参照領域７３ｂは、ソースコード５３のループに基づいて参照される領域である。具体的には、参照領域７３ｂは、ａ（１），ａ（３），…，ａ（９９９）のように規則的に間隔の空いた領域である。定義領域７３ａと参照領域７３ｂとを比較すると、両者は重複しない。このため、ソースコード５３のループは並列化可能であり、ソースコード５３に意味的な誤りはない。
【００９０】
定義領域７４ａは、ソースコード５４のループに基づいて定義される領域である。具体的には、定義領域７４ａは、ａ（２），ａ（４），ａ（６），…，ａ（１０００）のように規則的に間隔の空いた領域である。参照領域７４ｂは、ソースコード５４のループに基づいて参照される領域である。具体的には、参照領域７４ｂは、ａ（１），ａ（３），ａ（５），…，ａ（９９９）のように規則的に間隔の空いた領域である。定義領域７４ａと参照領域７４ｂとを比較すると、定義領域７４ａは偶数番目の要素のみ含むのに対して参照領域７４ｂは奇数番目の要素のみ含むため両者は重複しない。このため、ソースコード５４のループは並列化可能であり、ソースコード５４に意味的な誤りはない。
【００９１】
ここで、定義領域７１ａと参照領域７１ｂは、引数ｋ１，ｋ２，ｉｎから算出できる。このため、並列計算装置１００は、ループの実行前に、定義領域７１ａと参照領域７１ｂを算出して並列化不可であることを判定できる。同様に、定義領域７２ａと参照領域７２ｂは、引数ｋ１，ｋ２，ｋ３，ｋ４から算出できる。このため、並列計算装置１００は、ループの実行前に、定義領域７２ａと参照領域７２ｂを算出して並列化可能であることを判定できる。定義領域７３ａと参照領域７３ｂは、引数ｋ１，ｋ２から算出できる。このため、並列計算装置１００は、ループの実行前に、定義領域７３ａと参照領域７３ｂを算出して並列化可能であることを判定できる。定義領域７４ａと参照領域７４ｂは、引数ｋ１，ｋ２，ｉｎから算出できる。このため、並列計算装置１００は、ループの実行前に、定義領域７４ａと参照領域７４ｂを算出して並列化可能であることを判定できる。定義領域と参照領域が規則的領域である場合、ループの実行前に並列化可否を判定できる。
【００９２】
後述するように、コンパイル装置２００は、ループ内に配列の定義を検出すると、ソースコードの記載から、その定義領域が連続領域になるか規則的領域になるかそれ以外の領域（非規則的領域）になるか判定することができる。また、コンパイル装置２００は、ループ内に配列の参照を検出すると、ソースコードの記載から、その参照領域が連続領域になるか規則的領域になるか非規則的領域になるか判定することができる。
【００９３】
上記のように、連続的な定義領域または規則的な定義領域と、連続的な参照領域または規則的な参照領域とは、ループの実行前に比較することが可能である。一方、定義領域と参照領域の少なくとも一方が非規則的になる場合、定義領域と参照領域とをループの実行前に比較することは難しい。この場合、ループ内で並列化可否が判定されることになる。ただし、定義領域および参照領域は、連続的かまたは規則的であることが多い。このため、ループ外で検査処理を行う場合が多く、ループ内で検査処理を行う場合は少ない。
【００９４】
ところで、プログラミング言語の中には、ポインタ変数によって配列を指すことができるものもある。ポインタ変数が指す配列は、実行時に動的に変更され得る。このため、あるポインタ変数が実際に指している配列をソースコードから判定することは容易でない。そこで、コンパイル装置２００は、ソースコードに現れるポインタ変数はソースコードに定義されている任意の配列を指す可能性があると仮定して、定義領域と参照領域との比較が行われるようにオブジェクトコードを生成する。
【００９５】
図１６は、ソースコード例を示す第６の図である。
ソースコード５５には、サブルーチンｆｏｏ１５が記載されている。サブルーチンｆｏｏ１５は、引数としてｋ１，ｋ２を取得する。サブルーチンｆｏｏ１５は、長さがｋ２＋１の実数型の配列ｂと、実数型の配列を指すポインタ変数ａ１，ａ２とを定義する。サブルーチンｆｏｏ１５は、ポインタ変数ａ１に対して長さがｋ２＋１の配列を割り当てると共に、ポインタ変数ａ２がポインタ変数ａ１と同じ配列を指すように設定する。そして、サブルーチンｆｏｏ１５は、ループ変数ｎの値をｋ１からｋ２まで１ずつ増加させながらループを実行する。ループは、ポインタ変数ａ１が指す配列のｎ＋１番目の要素の定義と、ポインタ変数ａ２が指す配列のｎ番目の要素の参照とを含む。
【００９６】
ここで、定義に係る変数名は「ａ１」であり、参照に係る変数名は「ａ２」であるため、この定義される配列と参照される配列とは異なるようにも見える。しかし、実際にはポインタ変数ａ２はポインタ変数ａ１と同じ配列を指しているため、この定義される配列と参照される配列とは同一である。この場合、「ａ１」に対応する定義領域と「ａ２」に対応する参照領域とを比較して、ループの並列化可否を判定することが好ましい。
【００９７】
ただし、コンパイル装置２００は、ポインタ変数ａ１，ａ２が指す配列の同一性をコンパイル時に静的に判定することは難しい。そのため、コンパイル装置２００は、ポインタ変数ａ１，ａ２はソースコード５５に現れる任意の配列を指すものと仮定する。すなわち、コンパイル装置２００は、ポインタ変数ａ２が指す配列は、配列ｂと同一であり、ポインタ変数ａ１が指す配列とも同一であると仮定する。この場合、コンパイル装置２００は、配列ｂの定義領域とポインタ変数ａ２の参照領域との間の比較と、ポインタ変数ａ１の定義領域とポインタ変数ａ２の参照領域との間の比較とが行われるように、オブジェクトコードを生成する。なお、定義領域および参照領域は実行時のメモリアドレスによって表現されるため、異なる配列間の比較は実行時に重複なしと判定されることになる。
【００９８】
次に、並列計算装置１００およびコンパイル装置２００の機能について説明する。
図１７は、並列計算装置とコンパイル装置の機能例を示すブロック図である。
並列計算装置１００は、アドレス情報記憶部１２１、ループ前検査部１２２、ループ内検査部１２３およびメッセージ表示部１２４を有する。アドレス情報記憶部１２１は、ＲＡＭ１０２またはＨＤＤ１０３に確保した記憶領域を用いて実現できる。ループ前検査部１２２およびループ内検査部１２３は、オブジェクトコードから呼び出されるライブラリであるプログラムモジュールを用いて実現できる。ライブラリは、例えば、ＣＰＵコア１０１ａ〜１０１ｄの何れかによって実行される。ライブラリを実行するＣＰＵコアは、並列に動作する複数のスレッドのうちの１つを実行するＣＰＵコアであってもよい。メッセージ表示部１２４は、プログラムモジュールとして実現できる。
【００９９】
アドレス情報記憶部１２１は、アドレス情報を記憶する。アドレス情報は、ループ内検査部１２３によって生成されてアドレス情報記憶部１２１に格納され、ループ内検査部１２３から読み出される。アドレス情報は、定義された配列の要素のアドレス（個別定義アドレス）と、参照された配列の要素のアドレス（個別参照アドレス）とを含む。
【０１００】
ループ前検査部１２２は、コンパイル装置２００が生成したオブジェクトコードからループの実行直前に呼び出される。ループ前検査部１２２は、連続領域の定義、連続領域の参照、規則的領域の定義および規則的領域の参照に関するパラメータを取得する。パラメータは、「引数」や「変数」などと呼ぶこともできる。このパラメータの中には、コンパイル時には値が未確定であり実行時に値が確定するものが含まれ得る。ループ前検査部１２２は、取得したパラメータに基づいて、連続的な定義領域、連続的な参照領域、規則的な定義領域および規則的な参照領域を算出する。ループ前検査部１２２は、連続的または規則的な定義領域と連続的または規則的な参照領域とを比較し、ループの並列化可否を判定する。前述のように、定義領域と参照領域とが一部重複する場合は並列化不可と判定され、両者が一致するかまたは重複しない場合は並列化可能と判定される。
【０１０１】
ループ内検査部１２３は、コンパイル装置２００が生成したオブジェクトコードからループ内で呼び出される。このため、ループ内検査を行う場合には、ループの繰り返し処理１回につき１回以上、ループ内検査部１２３が呼び出されることになる。ただし、前述のように、多くの定義領域および参照領域は連続領域かまたは規則的領域に該当するため、ループ内検査部１２３が呼び出される可能性は低いと期待できる。ループ内検査部１２３は、個別定義アドレスや個別参照アドレスなど、ループ内検査に用いる情報を取得する。連続的な定義領域、連続的な参照領域、規則的な定義領域および規則的な参照領域に関する情報は、ループ前検査部１２２から取得するようにしてもよい。
【０１０２】
ループ内検査部１２３は、個別定義アドレスおよび個別参照アドレスをアドレス情報記憶部１２１に格納する。また、ループ内検査部１２３は、個別定義アドレスと、連続的な参照領域および規則的な参照領域とを比較する。前者が後者に包含される場合には、原則として並列化不可と判定される。また、ループ内検査部１２３は、個別定義アドレスと、アドレス情報記憶部１２１に蓄積された個別参照アドレスとを比較する。両者が一致する場合には、原則として並列化不可と判定される。また、ループ内検査部１２３は、個別参照アドレスと、連続的な定義領域および規則的な定義領域とを比較する。前者が後者に包含される場合には、原則として並列化不可と判定される。また、ループ内検査部１２３は、個別参照アドレスと、アドレス情報記憶部１２１に蓄積された個別定義アドレスとを比較する。両者が一致する場合には、原則として並列化不可と判定される。
【０１０３】
メッセージ表示部１２４は、ループ前検査部１２２またはループ内検査部１２３によってループが並列化不可と判定されると、並列化不可を警告するメッセージを生成する。メッセージ表示部１２４は、生成したメッセージをディスプレイ１１１に表示する。ただし、メッセージ表示部１２４は、生成したメッセージをＲＡＭ１０２やＨＤＤ１０３などに記憶されたログに追記してもよい。また、メッセージ表示部１２４は、生成したメッセージをネットワーク３０を介して他の装置に送信してもよい。また、メッセージ表示部１２４は、生成したメッセージを音として再生してもよい。
【０１０４】
コンパイル装置２００は、ソースコード記憶部２２１、中間コード記憶部２２２、オブジェクトコード記憶部２２３、フロントエンド部２２４、最適化部２２５およびバックエンド部２２６を有する。ソースコード記憶部２２１、中間コード記憶部２２２およびオブジェクトコード記憶部２２３は、ＲＡＭ２０２またはＨＤＤ２０３に確保した記憶領域を用いて実現できる。フロントエンド部２２４、最適化部２２５およびバックエンド部２２６は、プログラムモジュールを用いて実現できる。
【０１０５】
ソースコード記憶部２２１は、ユーザが作成したソースコード（前述のソースコード４１〜４９，５１〜５５など）を記憶する。ソースコードは、ＦＯＲＴＲＡＮなどのプログラミング言語を用いて記載されている。ソースコードには、ループが記載されていることがある。ループに対しては、ユーザによって並列化が指示されていることがある。並列化指示文は、プログラミング言語の仕様に定義されたものであってもよいし、ＯｐｅｎＭＰなどの拡張言語に従ってソースコードに付加されるものであってもよい。
【０１０６】
中間コード記憶部２２２は、ソースコードから変換された中間コードを記憶する。中間コードは、コンパイル装置２００の内部で使用される中間言語を用いて記載されている。オブジェクトコード記憶部２２３は、ソースコードに対応する機械可読なオブジェクトコードを記憶する。オブジェクトコードは、並列計算装置１００によって実行される。
【０１０７】
フロントエンド部２２４は、コンパイルのフロントエンド処理を行う。すなわち、フロントエンド部２２４は、ソースコード記憶部２２１からソースコードを読み出し、読み出したソースコードを解析する。ソースコードの解析には、字句解析、構文解析および意味解析が含まれる。フロントエンド部２２４は、ソースコードに対応する中間コードを生成し、生成した中間コードを中間コード記憶部２２２に格納する。
【０１０８】
また、フロントエンド部２２４は、ユーザから入力されたコンパイルコマンドに所定のコンパイルオプション（デバッグオプションなど）が付加されていた場合、ループの並列化可否を判定する検査処理の挿入を行う。検査処理の挿入は、ソースコードレベルで行ってもよいし、中間コードレベルで行ってもよい。
【０１０９】
フロントエンド部２２４は、ループ内から配列の定義の命令を抽出し、インデックスやループ変数などの記載に基づいて、定義領域が連続的領域になるか規則的領域になるか非規則的領域になるかを推定する。また、フロントエンド部２２４は、ループ内から配列の参照の命令を抽出し、インデックスやループ変数などの記載に基づいて、参照領域が連続的領域になるか規則的領域になるか非規則的領域になるかを推定する。フロントエンド部２２４は、連続的な定義領域、連続的な参照領域、規則的な定義領域および規則的な参照領域が存在する場合、ループ直前に、パラメータの値を算出してライブラリを呼び出す命令を挿入する。また、フロントエンド部２２４は、非規則的な定義領域および非規則的な参照領域が存在する場合、ループ内に、ライブラリを呼び出す命令を挿入する。
【０１１０】
最適化部２２５は、中間コード記憶部２２２から中間コードを読み出し、実行効率の高いオブジェクトコードが生成されるように、中間コードに対して各種の最適化を行う。最適化には、複数のＣＰＵコアを利用した並列化が含まれる。最適化部２２５は、中間コードの中から並列化可能な処理を検出し、複数のスレッドが並列に実行されるように中間コードを書き換える。ループ内で検査処理を行わない場合、そのループは並列化できる可能性がある。すなわち、ｎ回繰り返される処理が分割され、ｎ回のうちのｉ回目の処理とｊ回目の処理とが異なるＣＰＵコアによって実行され得る。一方、ループ内で検査処理を行う場合、繰り返し処理の間に依存関係が生じるためそのループは並列化されない。
【０１１１】
バックエンド部２２６は、コンパイルのバックエンド処理を行う。すなわち、バックエンド部２２６は、中間コード記憶部２２２から最適化済みの中間コードを読み出し、読み出した中間コードをオブジェクトコードに変換する。バックエンド部２２６は、中間コードからアセンブリ言語で記述されたアセンブリコードを生成し、アセンブリコードをオブジェクトコードに変換するようにしてもよい。バックエンド部２２６は、生成したオブジェクトコードをオブジェクトコード記憶部２２３に格納する。
【０１１２】
図１８は、ライブラリ呼び出しのパラメータ例を示す図である。
コンパイル装置２００によって生成されるオブジェクトコードは、ループの実行直前に、図１８に示すようなパラメータ８１〜８４の値を配列毎に算出し、ライブラリ（ループ前検査部１２２）を呼び出す。ライブラリの呼び出しは、例えば、配列単位で行われる。すなわち、同一の配列についての定義および参照についての情報は纏められる。
【０１１３】
パラメータ８１は、定義領域が連続領域になるような配列へのアクセス（連続領域定義）に関するパラメータである。パラメータ８１は、定義項目の個数を含む。定義項目の個数は、ループ内で行われる連続領域定義の個数を示す。定義項目の個数は、コンパイル時に算出できる。パラメータ８１は、定義項目毎に、先頭アドレスと領域サイズとを含む。先頭アドレスは、連続領域定義によってアクセスされる配列の要素のうち先頭の要素を示すメモリアドレスである。領域サイズは、連続領域定義によってアクセスされる定義領域の大きさ（バイト数）である。先頭アドレスおよび領域サイズは、実行時に算出される。
【０１１４】
例えば、図６に示したソースコード４１の場合、「ａ（ｎ＋ｉｎ）」への値の代入が連続領域定義に該当する。この場合、定義項目の個数は１、先頭アドレスはａ（２）を示すメモリアドレス、領域サイズは４バイト×１０００＝４０００バイトとなる。なお、ここでは、実数型の要素１個は４バイトで表現されるものとしている。また、配列の定義が連続領域定義であるか否かの判定方法については後述する。
【０１１５】
パラメータ８２は、参照領域が連続領域になるような配列へのアクセス（連続領域参照）に関するパラメータである。パラメータ８２は、参照項目の個数を含む。参照項目の個数は、ループ内で行われる連続領域参照の個数を示す。参照項目の個数は、コンパイル時に算出できる。パラメータ８２は、参照項目毎に、先頭アドレスと領域サイズとを含む。先頭アドレスは、連続領域参照によってアクセスされる配列の要素のうち先頭の要素を示すメモリアドレスである。領域サイズは、連続領域参照によってアクセスされる参照領域の大きさ（バイト数）である。先頭アドレスおよび領域サイズは、実行時に算出される。
【０１１６】
例えば、図６に示したソースコード４１の場合、「ａ（ｎ）」の値の取得が連続領域参照に該当する。この場合、参照項目の個数は１、先頭アドレスはａ（１）を示すメモリアドレス、領域サイズは４バイト×１０００＝４０００バイトとなる。なお、配列の参照が連続領域参照であるか否かの判定方法については後述する。
【０１１７】
パラメータ８３は、定義領域が規則的領域になるような配列へのアクセス（規則的領域定義）に関するパラメータである。パラメータ８３は、定義項目の個数を含む。定義項目の個数は、ループ内で行われる規則的領域定義の個数を示す。定義項目の個数は、コンパイル時に算出できる。パラメータ８３は、定義項目毎に、先頭アドレスと要素サイズと次元数とを含む。先頭アドレスは、規則的領域定義によってアクセスされる配列の要素のうち先頭の要素を示すメモリアドレスである。先頭アドレスは、実行時に算出される。要素サイズは、配列の要素１個の大きさ（バイト数）である。次元数は、インデックスの次元数である。要素サイズおよび次元数は、コンパイル時に算出される。
【０１１８】
パラメータ８３は、インデックスの次元毎に、繰り返し回数とアドレス増分とを含む。繰り返し回数は、ループを実行した場合にその次元のインデックスの値が何通りに変化するかを示す。アドレス増分は、その次元のインデックスの値が１つ変化するときのメモリアドレスの増加量である。繰り返し回数およびアドレス増分は、実行時に算出される。
【０１１９】
例えば、図１３に示したソースコード５４の場合、「ａ（ｎ＋ｉｎ）」への値の代入が規則的領域定義に該当する。この場合、定義項目の個数は１、先頭アドレスはａ（２）を示すメモリアドレス、要素サイズは４バイト、次元数は１となる。また、繰り返し回数は（ｋ２−ｋ１＋１）／２＝５００回、アドレス増分は４バイト×２＝８バイトとなる。なお、配列の定義が規則的領域定義であるか否かの判定方法については後述する。
【０１２０】
パラメータ８４は、参照領域が規則的領域になるような配列へのアクセス（規則的領域参照）に関するパラメータである。パラメータ８４は、参照項目の個数を含む。参照項目の個数は、ループ内で行われる規則的領域参照の個数を示す。参照項目の個数は、コンパイル時に算出できる。パラメータ８４は、参照項目毎に、先頭アドレスと要素サイズと次元数とを含む。先頭アドレスは、規則的領域参照によってアクセスされる配列の要素のうち先頭の要素を示すメモリアドレスである。先頭アドレスは、実行時に算出される。要素サイズは、配列の要素１個の大きさ（バイト数）である。次元数は、インデックスの次元数である。要素サイズおよび次元数は、コンパイル時に算出される。
【０１２１】
パラメータ８４は、インデックスの次元毎に、繰り返し回数とアドレス増分とを含む。繰り返し回数は、ループを実行した場合にその次元のインデックスの値が何通りに変化するかを示す。アドレス増分は、その次元のインデックスの値が１つ変化するときのメモリアドレスの増加量である。繰り返し回数およびアドレス増分は、実行時に算出される。
【０１２２】
例えば、図１３に示したソースコード５４の場合、「ａ（ｎ）」の値の取得が規則的領域参照に該当する。この場合、参照項目の個数は１、先頭アドレスはａ（１）を示すメモリアドレス、要素サイズは４バイト、次元数は１となる。また、繰り返し回数は（ｋ２−ｋ１＋１）／２＝５００回、アドレス増分は４バイト×２＝８バイトとなる。なお、配列の参照が規則的領域参照であるか否かの判定方法については後述する。
【０１２３】
図１９は、エラーメッセージの表示例を示す図である。
エラーメッセージ９１は、ループが並列化不可と判定された場合にメッセージ表示部１２４によって生成される。エラーメッセージ９１は、例えば、ユーザがプログラムの起動コマンドを入力したコマンド入力ウィンドウに表示される。一例として、ソースコードの１３行目に記載された配列の定義に対応する定義領域とソースコードの１４行目に記載された配列の参照に対応する参照領域とが一部重複していたとする。この場合、例えば、「行番号１３の変数名ａと行番号１４の変数名ａの引用は、特定の繰り返しの実行に依存しています。このループの実行結果は不定です。」という文が表示される。この文は、ＲＡＭ１０２やＨＤＤ１０３などに記憶されたエラーログに追記されてもよい。
【０１２４】
次に、コンパイル、ループ前検査およびループ内検査の手順について説明する。
図２０は、コンパイルの手順例を示すフローチャートである。
ここでは、主に検査機能の追加に関する処理について説明する。
【０１２５】
（Ｓ１１０）フロントエンド部２２４は、未選択のループが存在するか判断する。未選択のループが存在する場合はステップＳ１１１に処理が進み、未選択のループが存在しない場合はフロントエンド部２２４の処理が終了する。
【０１２６】
（Ｓ１１１）フロントエンド部２２４は、ループを１つ選択する。
（Ｓ１１２）フロントエンド部２２４は、ステップＳ１１１で選択したループが並列化指示のあるループであるか判断する。ループに対して並列化を指示する構文は、プログラミング言語の仕様に規定されていることもあるし、そのプログラミング言語とは異なる拡張言語によって規定されていることもある。並列化指示のあるループである場合はステップＳ１１３に処理が進み、それ以外の場合はステップＳ１１０に処理が進む。
【０１２７】
（Ｓ１１３）フロントエンド部２２４は、ステップＳ１１１で選択したループの中から配列の定義を示す定義項目を抽出し、定義項目を列挙した定義項目リストを生成する。定義項目は、例えば、代入文の左辺（等号の左側）に記載された項目であり、配列を示す変数名とインデックスとを含む。また、フロントエンド部２２４は、ステップＳ１１１で選択したループの中から配列の参照を示す参照項目を抽出し、参照項目を列挙した参照項目リストを生成する。参照項目は、例えば、代入文の右辺（等号の右側）に記載されたものであり、配列を示す変数名とインデックスとを含む。定義項目および参照項目には、配列を指すポインタ変数を用いたものが含まれる。
【０１２８】
（Ｓ１１４）フロントエンド部２２４は、ステップＳ１１３で生成した定義項目リストと参照項目リストとを比較し、片方のリストのみに現れる変数名を検出する。そして、フロントエンド部２２４は、検出した変数名を含む定義項目を定義項目リストから削除し、検出した変数名を含む参照項目を参照項目リストから削除する。定義のみ行われ参照されない配列、および、参照のみ行われ定義されない配列は、繰り返し処理に依存関係を生じさせないためである。ただし、ポインタ変数は任意の配列を指すことができるため、ポインタ変数の変数名を含む定義項目および参照項目は削除対象としない。
【０１２９】
（Ｓ１１５）フロントエンド部２２４は、定義項目リストに含まれる定義項目および参照項目リストに含まれる参照項目を、変数名によって分類する。フロントエンド部２２４は、変数名が同じ定義項目および参照項目の間でインデックスが全て同一である場合、その定義項目を定義項目リストから削除し、その参照項目を参照項目リストから削除する。インデックスが同一であれば、ｉ回目の処理で定義される要素とｊ回目の処理で参照される要素とが同一になることはないからである（ｉ，ｊは異なる正の整数）。ただし、ポインタ変数の変数名を含む定義項目および参照項目は削除対象としない。
【０１３０】
（Ｓ１１６）フロントエンド部２２４は、定義項目リストの中で、変数名とインデックスが同じ定義項目を纏める。また、フロントエンド部２２４は、参照項目リストの中で、変数名とインデックスが同じ参照項目を纏める。
【０１３１】
（Ｓ１１７）フロントエンド部２２４は、定義項目リストの中から定義領域が連続領域になる定義項目を抽出する。定義領域が連続領域になる定義項目は、以下に示す条件＃１を満たす定義項目である。また、フロントエンド部２２４は、参照項目リストの中から参照領域が連続領域になる参照項目を抽出する。参照領域が連続領域になる参照項目は、以下に示す条件＃１を満たす参照項目である。
【０１３２】
条件＃１は、次の（１ａ），（１ｂ），（１ｃ）の全てを満たすことである。（１ａ）インデックスの中にループ変数が１つだけ現れる。（１ｂ）インデックスがループ変数単独であるか、または、ループ変数と定数または他の変数との加減算として表されている。（１ｃ）ループ変数の増分が省略されているか、または、ループ変数の増分が１に指定されている。例えば、「ａ（ｎ）」や「ａ（ｎ＋ｉｎ）」は上記（１ｂ）を満たす一方、「ａ（２ｎ）」は上記（１ｂ）を満たさない。また、例えば、「ＤＯ  ＣＯＮＣＵＲＲＥＮＴ（ｎ＝１：１０００：１）」は上記（１ｃ）を満たす一方、「ＤＯ  ＣＯＮＣＵＲＲＥＮＴ（ｎ＝１：１０００：２）」は上記（１ｃ）を満たさない。
【０１３３】
フロントエンド部２２４は、抽出した定義項目について図１８のパラメータ８１を生成し、抽出した参照項目について図１８のパラメータ８２を生成する。ただし、パラメータ８１，８２には、コンパイル時に決定できる値が含まれていることもあるし、コンパイル時に決定されない値が含まれていることもある。後者については、実行時に決定される変数の値からパラメータの値を算出する方法が特定される。例えば、図６のソースコード４１の場合、領域サイズは（ｋ２−ｋ１＋１）×４によって算出できる。
【０１３４】
（Ｓ１１８）フロントエンド部２２４は、定義項目リストの中から定義領域が規則的領域になる定義項目を抽出する。定義領域が規則的領域になる定義項目は、以下に示す条件＃２または条件＃３を満たす定義項目である。また、フロントエンド部２２４は、参照項目リストの中から参照領域が規則的領域になる参照項目を抽出する。参照領域が規則的領域になるものは、以下に示す条件＃２または条件＃３を満たす参照項目である。
【０１３５】
条件＃２は、次の（２ａ），（２ｂ）の両方を満たすことである。（２ａ）次元数が２以上であり、２以上のループ変数が互いに異なる次元に現れる。（２ｂ）ループ変数が現れる次元それぞれについて、インデックスがループ変数単独であるか、または、ループ変数と定数または他の変数との加減算として表されている。例えば、「ＤＯ  ＤＯＮＣＵＲＲＥＮＴ（ｎ１＝１：１０００，ｎ２＝１：１０００）…ａ（ｎ１＋ｋ１，ｎ２）」は、上記（２ａ）および上記（２ｂ）を満たす。
【０１３６】
条件＃３は、次の（３ａ），（３ｂ），（３ｃ）の全てを満たすことである。（３ａ）インデックスの中にループ変数が１つだけ現れる。（３ｂ）インデックスがループ変数単独であるか、または、ループ変数と定数または他の変数との加減算として表されている。（３ｃ）ループ変数の増分が１より大きいか、または、ループ変数の増分が変数であり１より大きい可能性がある。例えば、「ＤＯ  ＤＯＮＣＵＲＲＥＮＴ（ｎ＝１：１０００：ｋ）…ａ（ｎ）」は、上記（３ａ）〜（３ｃ）を満たす。
【０１３７】
フロントエンド部２２４は、抽出した定義項目について図１８のパラメータ８３を生成し、抽出した参照項目について図１８のパラメータ８４を生成する。ただし、パラメータ８３，８４には、コンパイル時に決定できる値が含まれていることもあるし、コンパイル時に決定されない値が含まれていることもある。後者については、実行時に決定される変数の値からパラメータの値を算出する方法が特定される。例えば、図１３のソースコード５４の場合、繰り返し回数は（ｋ２−ｋ１＋１）／２によって算出できる。
【０１３８】
（Ｓ１１９）フロントエンド部２２４は、ステップＳ１１７で生成したパラメータ８１，８２およびステップＳ１１８で生成したパラメータ８３，８４について、同じ配列（同じ変数名）に関するパラメータ同士を纏める。ただし、ポインタ変数は任意の配列を指す可能性があるため、フロントエンド部２２４は、ポインタ変数が指す配列は他の全ての配列と同一であると仮定する。フロントエンド部２２４は、配列毎（変数名毎）に、ループの直前にライブラリ呼び出し命令を挿入する。ライブラリ呼び出しでは、その配列に対応するパラメータ８１〜８４が引数として指定される。
【０１３９】
（Ｓ１２０）フロントエンド部２２４は、ステップＳ１１９で生成したライブラリ呼び出しによって全ての定義項目と参照項目がカバーされるか判断する。すなわち、フロントエンド部２２４は、定義項目リストに含まれる全ての定義項目および参照項目リストに含まれる全ての参照項目が上記の条件＃１〜＃３の何れかに該当するか判断する。全ての定義項目および参照項目が条件＃１〜＃３の何れかに該当する場合、フロントエンド部２２４の処理が終了する。条件＃１〜＃３の何れにも該当しない定義項目または参照項目が存在する場合、ステップＳ１２１に処理が進む。
【０１４０】
（Ｓ１２１）フロントエンド部２２４は、カウンタＣを１に初期化する命令をループ直前に挿入する。また、フロントエンド部２２４は、条件＃１〜＃３に該当しない定義項目について、ループ内のその定義項目が現れる場所にライブラリ呼び出し命令を挿入する。このライブラリ呼び出しでは、定義される要素のアドレスが引数として渡される。また、フロントエンド部２２４は、条件＃１〜＃３に該当しない参照項目について、ループ内のその参照項目が現れる場所にライブラリ呼び出し命令を挿入する。このライブラリ呼び出しでは、参照される要素のアドレスが引数として渡される。また、フロントエンド部２２４は、カウンタＣに１を加算する命令をループ終端に挿入する。
【０１４１】
図２１は、ループ前検査の手順例を示すフローチャートである。
（Ｓ２１０）ループ前検査部１２２は、パラメータ８１が示す連続的な定義領域とパラメータ８２が示す連続的な参照領域とを比較し、繰り返し処理の依存性を検査する。この「連続・連続間検査」については図２２を用いて説明する。
【０１４２】
（Ｓ２１１）ループ前検査部１２２は、パラメータ８１が示す連続的な定義領域とパラメータ８４が示す規則的な参照領域とを比較し、繰り返し処理の依存性を検査する。この「連続・規則性間検査」については図２３を用いて説明する。
【０１４３】
（Ｓ２１２）ループ前検査部１２２は、パラメータ８３が示す規則的な定義領域とパラメータ８２が示す連続的な参照領域とを比較し、繰り返し処理の依存性を検査する。この「規則性・連続間検査」については図２４を用いて説明する。
【０１４４】
（Ｓ２１３）ループ前検査部１２２は、パラメータ８３が示す規則的な定義領域とパラメータ８４が示す規則的な参照領域とを比較し、繰り返し処理の依存性を検査する。この「規則性・規則性間検査」については図２５を用いて説明する。
【０１４５】
図２２は、連続・連続間検査の手順例を示すフローチャートである。
（Ｓ２２０）ループ前検査部１２２は、パラメータ８１（連続領域定義に関するパラメータ）の中から定義項目を１つ選択する。
【０１４６】
（Ｓ２２１）ループ前検査部１２２は、パラメータ８２（連続領域参照に関するパラメータ）の中から参照項目を１つ選択する。
（Ｓ２２２）ループ前検査部１２２は、定義項目の先頭アドレスと参照項目の先頭アドレスとが同一であり、かつ、定義項目の領域サイズと参照項目の領域サイズが同一であるか判断する。先頭アドレスと領域サイズの両方が同一である場合、定義領域と参照領域が完全一致する。この場合、ステップＳ２２５に処理が進む。先頭アドレスと領域サイズの少なくとも一方が異なる場合、ステップＳ２２３に処理が進む。
【０１４７】
（Ｓ２２３）ループ前検査部１２２は、定義項目が示す定義領域と参照項目が示す参照領域とが一部重複するか判断する。例えば、ループ前検査部１２２は、定義項目の先頭アドレスに定義項目の領域サイズを加えて末尾アドレスを算出する。定義項目の先頭アドレスと末尾アドレスの間に参照項目の先頭アドレスがある場合、定義領域と参照領域が一部重複している。また、ループ前検査部１２２は、参照項目の先頭アドレスに参照項目の領域サイズを加えて末尾アドレスを算出する。参照項目の先頭アドレスと末尾アドレスの間に定義項目の先頭アドレスがある場合、定義領域と参照領域が一部重複している。定義領域と参照領域が一部重複する場合はステップＳ２２４に処理が進み、定義領域と参照領域が重複していない場合はステップＳ２２５に処理が進む。
【０１４８】
（Ｓ２２４）メッセージ表示部１２４は、エラーメッセージ９１を生成する。メッセージ表示部１２４は、エラーメッセージ９１をディスプレイ１１１に表示する。
（Ｓ２２５）ループ前検査部１２２は、パラメータ８２に未選択の参照項目があるか判断する。未選択の参照項目がある場合はステップＳ２２１に処理が進み、全ての参照項目を選択した場合はステップＳ２２６に処理が進む。
【０１４９】
（Ｓ２２６）ループ前検査部１２２は、パラメータ８１に未選択の定義項目があるか判断する。未選択の定義項目がある場合はステップＳ２２０に処理が進み、全ての定義項目を選択した場合は連続・連続間検査が終了する。
【０１５０】
図２３は、連続・規則性間検査の手順例を示すフローチャートである。
（Ｓ２３０）ループ前検査部１２２は、パラメータ８１（連続領域定義に関するパラメータ）の中から定義項目を１つ選択する。
【０１５１】
（Ｓ２３１）ループ前検査部１２２は、パラメータ８４（規則的領域参照に関するパラメータ）の中から参照項目を１つ選択する。
（Ｓ２３２）ループ前検査部１２２は、参照項目に基づいて規則的にアクセスされる各領域のアドレス（参照アドレス）を算出し、定義項目が示す定義領域と比較する。例えば、ループ前検査部１２２は、定義項目の先頭アドレスに定義項目の領域サイズを加えて末尾アドレスを算出する。また、ループ前検査部１２２は、参照項目の先頭アドレスにアドレス増分を繰り返し加算していくことで、全ての参照アドレスを算出する。ループ前検査部１２２は、各参照アドレスが、定義項目の先頭アドレスおよび末尾アドレスによって特定される定義領域に包含されるか判定する。
【０１５２】
（Ｓ２３３）ループ前検査部１２２は、全ての参照アドレスが定義領域外であるか判断する。全ての参照アドレスが定義領域外である場合、定義領域と参照領域とが重複しない。全ての参照アドレスが定義領域外である場合はステップＳ２３６に処理が進み、少なくとも１つの参照アドレスが定義領域内である場合はステップＳ２３４に処理が進む。
【０１５３】
（Ｓ２３４）ループ前検査部１２２は、全ての参照アドレスが定義領域内であるか判断する。全ての参照アドレスが定義領域内である場合、定義領域と参照領域とが完全一致する。全ての参照アドレスが定義領域内である場合、ステップＳ２３６に処理が進む。一部の参照アドレスが定義領域内かつ一部の参照アドレスが定義領域外である場合、すなわち、定義領域と参照領域とが一部重複する場合、ステップＳ２３５に処理が進む。
【０１５４】
（Ｓ２３５）メッセージ表示部１２４は、エラーメッセージ９１を生成する。メッセージ表示部１２４は、エラーメッセージ９１をディスプレイ１１１に表示する。
（Ｓ２３６）ループ前検査部１２２は、パラメータ８４に未選択の参照項目があるか判断する。未選択の参照項目がある場合はステップＳ２３１に処理が進み、全ての参照項目を選択した場合はステップＳ２３７に処理が進む。
【０１５５】
（Ｓ２３７）ループ前検査部１２２は、パラメータ８１に未選択の定義項目があるか判断する。未選択の定義項目がある場合はステップＳ２３０に処理が進み、全ての定義項目を選択した場合は連続・規則性間検査が終了する。
【０１５６】
図２４は、規則性・連続間検査の手順例を示すフローチャートである。
（Ｓ２４０）ループ前検査部１２２は、パラメータ８２（連続領域参照に関するパラメータ）の中から参照項目を１つ選択する。
【０１５７】
（Ｓ２４１）ループ前検査部１２２は、パラメータ８３（規則的領域定義に関するパラメータ）の中から定義項目を１つ選択する。
（Ｓ２４２）ループ前検査部１２２は、定義項目に基づいて規則的にアクセスされる各領域のアドレス（定義アドレス）を算出し、参照項目が示す参照領域と比較する。例えば、ループ前検査部１２２は、参照項目の先頭アドレスに参照項目の領域サイズを加えて末尾アドレスを算出する。また、ループ前検査部１２２は、定義項目の先頭アドレスにアドレス増分を繰り返し加算していくことで、全ての定義アドレスを算出する。ループ前検査部１２２は、各定義アドレスが、参照項目の先頭アドレスおよび末尾アドレスによって特定される参照領域に包含されるか判定する。
【０１５８】
（Ｓ２４３）ループ前検査部１２２は、全ての定義アドレスが参照領域外であるか判断する。全ての定義アドレスが参照領域外である場合、定義領域と参照領域とが重複しない。全ての定義アドレスが参照領域外である場合はステップＳ２４６に処理が進み、少なくとも１つの定義アドレスが参照領域内である場合はステップＳ２４４に処理が進む。
【０１５９】
（Ｓ２４４）ループ前検査部１２２は、全ての定義アドレスが参照領域内であるか判断する。全ての定義アドレスが参照領域内である場合、定義領域と参照領域とが完全一致する。全ての定義アドレスが参照領域内である場合、ステップＳ２４６に処理が進む。一部の定義アドレスが参照領域内かつ一部の定義アドレスが参照領域外である場合、すなわち、定義領域と参照領域とが一部重複する場合、ステップＳ２４５に処理が進む。
【０１６０】
（Ｓ２４５）メッセージ表示部１２４は、エラーメッセージ９１を生成する。メッセージ表示部１２４は、エラーメッセージ９１をディスプレイ１１１に表示する。
（Ｓ２４６）ループ前検査部１２２は、パラメータ８３に未選択の定義項目があるか判断する。未選択の定義項目がある場合はステップＳ２４１に処理が進み、全ての定義項目を選択した場合はステップＳ２４７に処理が進む。
【０１６１】
（Ｓ２４７）ループ前検査部１２２は、パラメータ８２に未選択の参照項目があるか判断する。未選択の参照項目がある場合はステップＳ２４０に処理が進み、全ての参照項目を選択した場合は規則性・連続間検査が終了する。
【０１６２】
図２５は、規則性・規則性間検査の手順例を示すフローチャートである。
（Ｓ２５０）ループ前検査部１２２は、パラメータ８３（規則的領域定義に関するパラメータ）の中から定義項目を１つ選択する。
【０１６３】
（Ｓ２５１）ループ前検査部１２２は、パラメータ８４（規則的領域参照に関するパラメータ）の中から参照項目を１つ選択する。
（Ｓ２５２）ループ前検査部１２２は、定義領域の先頭から末尾までの全体範囲と参照領域の先頭から末尾までの全体範囲とに重複があるか判断する。例えば、ループ前検査部１２２は、定義項目の先頭アドレスに定義項目のアドレス増分×（繰り返し回数−１）を加算することで末尾アドレスを算出する。また、ループ前検査部１２２は、参照項目の先頭アドレスに参照項目のアドレス増分×（繰り返し回数−１）を加算することで末尾アドレスを算出する。ループ前検査部１２２は、連続・連続間検査の場合と同様に、定義領域の全体範囲と参照領域の全体範囲を比較する。両者に重複がある場合はステップＳ２５３に処理が進み、重複がない場合はステップＳ２５９に処理が進む。
【０１６４】
（Ｓ２５３）ループ前検査部１２２は、定義項目と参照項目の間で、先頭アドレスと繰り返し回数とアドレス増分の全てが一致するか判断する。先頭アドレスと繰り返し回数とアドレス増分の全てが一致する場合、定義領域と参照領域が完全一致する。全てが一致する場合、ステップＳ２５９に処理が進む。先頭アドレスと繰り返し回数とアドレス増分の少なくとも１つが異なる場合、ステップＳ２５４に処理が進む。
【０１６５】
（Ｓ２５４）ループ前検査部１２２は、定義項目と参照項目の間で先頭アドレスが一致するか判断する。先頭アドレスが一致する場合はステップＳ２５７に処理が進み、先頭アドレスが一致しない場合はステップＳ２５５に処理が進む。なお、前者の場合は、繰り返し回数とアドレス増分の少なくとも一方が異なっている。
【０１６６】
（Ｓ２５５）ループ前検査部１２２は、定義項目と参照項目の間で、繰り返し回数とアドレス増分が一致するか判断する。先頭アドレスは異なるが繰り返し回数とアドレス増分は一致する場合、ステップＳ２５６に処理が進む。先頭アドレスに加えて繰り返し回数とアドレス増分の少なくとも一方も異なる場合、ステップＳ２５７に処理が進む。
【０１６７】
（Ｓ２５６）ループ前検査部１２２は、定義項目の先頭アドレスと参照項目の先頭アドレスの差を算出し、差がアドレス増分の整数倍であるか判断する。繰り返し回数とアドレス増分が一致し、かつ、先頭アドレスの差がアドレス増分の整数倍であれば、定義領域と参照領域は一部重複する。この場合、ステップＳ２５８に処理が進む。一方、繰り返し回数とアドレス増分が一致し、かつ、先頭アドレスの差がアドレス増分の整数倍でなければ、定義領域と参照領域は重複しない。この場合、ステップＳ２５９に処理が進む。
【０１６８】
（Ｓ２５７）ループ前検査部１２２は、定義項目に基づいて規則的にアクセスされる各領域のアドレス（定義アドレス）を算出する。また、ループ前検査部１２２は、参照項目に基づいて規則的にアクセスされる各領域のアドレス（参照アドレス）を算出する。ループ前検査部１２２は、定義アドレスと参照アドレスを網羅的に比較し、一部の定義アドレスと参照アドレスの組のみが一致するか判断する。一部の定義アドレスと参照アドレスの組のみが一致する場合、ステップＳ２５８に処理が進む。全ての定義アドレスについてそれと一致する参照アドレスが存在しないか、または、全ての定義アドレスについてそれと一致する参照アドレスが存在する場合、ステップＳ２５９に処理が進む。なお、多くの定義項目および参照項目は、ステップＳ２５２〜Ｓ２５６の判断条件によってステップＳ２５８に進むか否か判断できるため、ステップＳ２５７が実行される可能性は低い。
【０１６９】
（Ｓ２５８）メッセージ表示部１２４は、エラーメッセージ９１を生成する。メッセージ表示部１２４は、エラーメッセージ９１をディスプレイ１１１に表示する。
（Ｓ２５９）ループ前検査部１２２は、パラメータ８４に未選択の参照項目があるか判断する。未選択の参照項目がある場合はステップＳ２５１に処理が進み、全ての参照項目を選択した場合はステップＳ２６０に処理が進む。
【０１７０】
（Ｓ２６０）ループ前検査部１２２は、パラメータ８３に未選択の定義項目があるか判断する。未選択の定義項目がある場合はステップＳ２５０に処理が進み、全ての定義項目を選択した場合は規則性・規則性間検査が終了する。
【０１７１】
図２６は、ループ内検査の手順例を示すフローチャートである。
（Ｓ３１０）並列計算装置１００は、コンパイル装置２００によって生成されたオブジェクトコードに基づいて、ループの実行前にカウンタＣを１に初期化する。
【０１７２】
（Ｓ３１１）並列計算装置１００は、コンパイル装置２００によって生成されたオブジェクトコードに基づいて、ループ前に検査されなかった定義項目に対応して、ループ内においてループ内検査部１２３を呼び出す。ループ内検査部１２３は、個別定義検査を実行する。「個別定義検査」については図２７を用いて説明する。
【０１７３】
（Ｓ３１２）並列計算装置１００は、コンパイル装置２００によって生成されたオブジェクトコードに基づいて、ループ前に検査されなかった参照項目に対応して、ループ内においてループ内検査部１２３を呼び出す。ループ内検査部１２３は、個別参照検査を実行する。「個別参照検査」については図２８を用いて説明する。
【０１７４】
（Ｓ３１３）並列計算装置１００は、コンパイル装置２００によって生成されたオブジェクトコードに基づいて、カウンタＣに１を加算する。
（Ｓ３１４）並列計算装置１００は、コンパイル装置２００によって生成されたオブジェクトコードに基づいて、ループの終了条件を満たしたか（例えば、ループ変数の値が上限値に達したか）判断する。ループの終了条件を満たした場合はループ内検査が終了し、ループの終了条件を満たしていない場合はステップＳ３１１に処理が進む。
【０１７５】
図２７は、個別定義検査の手順例を示すフローチャートである。
（Ｓ３２０）ループ内検査部１２３は、パラメータ８２が示す参照項目に基づいて、現在のカウンタＣに対応する参照アドレス、すなわち、連続的な参照領域のうちループ変数の値が現在と同じときに参照される領域のアドレスを算出する。
【０１７６】
（Ｓ３２１）ループ内検査部１２３は、ループ内検査部１２３が呼び出されるときに定義された領域のアドレス（最新の個別定義アドレス）と、パラメータ８２が示す連続的な参照領域とを比較する。また、ループ内検査部１２３は、最新の個別定義アドレスとステップＳ３２０の参照アドレスとを比較する。ループ内検査部１２３は、最新の個別定義アドレスが連続的な参照領域内にあり、かつ、ステップＳ３２０の参照アドレスと異なるか判断する。上記条件を満たす場合、最新の個別定義アドレスの示す要素が、ループ変数の値が異なる処理において参照されることになる。この条件を満たす場合はステップＳ３２６に処理が進み、満たさない場合はステップＳ３２２に処理が進む。
【０１７７】
（Ｓ３２２）ループ内検査部１２３は、パラメータ８４が示す参照項目に基づいて、現在のカウンタＣに対応する参照アドレス、すなわち、規則的な参照領域のうちループ変数の値が現在と同じときに参照される領域のアドレスを算出する。
【０１７８】
（Ｓ３２３）ループ内検査部１２３は、最新の個別定義アドレスとパラメータ８４が示す規則的な参照領域とを比較する。また、ループ内検査部１２３は、最新の個別定義アドレスとステップＳ３２２の参照アドレスとを比較する。ループ内検査部１２３は、最新の個別定義アドレスが規則的な参照領域内にあり、かつ、ステップＳ３２２の参照アドレスと異なるか判断する。上記条件を満たす場合、最新の個別定義アドレスの示す要素が、ループ変数の値が異なる処理において参照されることになる。この条件を満たす場合はステップＳ３２６に処理が進み、満たさない場合はステップＳ３２４に処理が進む。
【０１７９】
（Ｓ３２４）ループ内検査部１２３は、最新の個別定義アドレスが、アドレス情報記憶部１２１に登録されている個別参照アドレスの何れかと一致するか判断する。また、ループ内検査部１２３は、現在のカウンタＣが、当該一致する個別参照アドレスに対応付けられているカウンタの値と異なるか判断する。この条件を満たす場合はステップＳ３２６に処理が進み、満たさない場合はステップＳ３２５に処理が進む。
【０１８０】
（Ｓ３２５）ループ内検査部１２３は、最新の個別定義アドレスと現在のカウンタＣを対応付けて、アドレス情報記憶部１２１に登録する。
（Ｓ３２６）メッセージ表示部１２４は、エラーメッセージ９１を生成する。メッセージ表示部１２４は、エラーメッセージ９１をディスプレイ１１１に表示する。
【０１８１】
図２８は、個別参照検査の手順例を示すフローチャートである。
（Ｓ３３０）ループ内検査部１２３は、パラメータ８１が示す定義項目に基づいて、現在のカウンタＣに対応する定義アドレス、すなわち、連続的な定義領域のうちループ変数の値が現在と同じときに定義される領域のアドレスを算出する。
【０１８２】
（Ｓ３３１）ループ内検査部１２３は、ループ内検査部１２３が呼び出されるときに参照された領域のアドレス（最新の個別参照アドレス）と、パラメータ８１が示す連続的な定義領域とを比較する。また、ループ内検査部１２３は、最新の個別参照アドレスとステップＳ３３０の定義アドレスとを比較する。ループ内検査部１２３は、最新の個別参照アドレスが連続的な定義領域内にあり、かつ、ステップＳ３３０の定義アドレスと異なるか判断する。上記条件を満たす場合、最新の個別参照アドレスの示す要素が、ループ変数の値が異なる処理において定義されることになる。この条件を満たす場合はステップＳ３３６に処理が進み、満たさない場合はステップＳ３３２に処理が進む。
【０１８３】
（Ｓ３３２）ループ内検査部１２３は、パラメータ８３が示す定義項目に基づいて、現在のカウンタＣに対応する定義アドレス、すなわち、規則的な定義領域のうちループ変数の値が現在と同じときに定義される領域のアドレスを算出する。
【０１８４】
（Ｓ３３３）ループ内検査部１２３は、最新の個別参照アドレスとパラメータ８３が示す規則的な定義領域とを比較する。また、ループ内検査部１２３は、最新の個別参照アドレスとステップＳ３３２の定義アドレスとを比較する。ループ内検査部１２３は、最新の個別参照アドレスが規則的な定義領域内にあり、かつ、ステップＳ３３２の定義アドレスと異なるか判断する。上記条件を満たす場合、最新の個別参照アドレスの示す要素が、ループ変数の値が異なる処理において定義されることになる。この条件を満たす場合はステップＳ３３６に処理が進み、満たさない場合はステップＳ３３４に処理が進む。
【０１８５】
（Ｓ３３４）ループ内検査部１２３は、最新の個別参照アドレスが、アドレス情報記憶部１２１に登録されている個別定義アドレスの何れかと一致するか判断する。また、ループ内検査部１２３は、現在のカウンタＣが、当該一致する個別定義アドレスに対応付けられているカウンタの値と異なるか判断する。この条件を満たす場合はステップＳ３３６に処理が進み、満たさない場合はステップＳ３３５に処理が進む。
【０１８６】
（Ｓ３３５）ループ内検査部１２３は、最新の個別参照アドレスと現在のカウンタＣを対応付けて、アドレス情報記憶部１２１に登録する。
（Ｓ３３６）メッセージ表示部１２４は、エラーメッセージ９１を生成する。メッセージ表示部１２４は、エラーメッセージ９１をディスプレイ１１１に表示する。
【０１８７】
第３の実施の形態の情報処理システムによれば、定義領域と参照領域が引数に依存する場合であっても、両者がそれぞれ連続領域または規則的領域であれば、ループの実行直前に定義領域と参照領域とを効率的に比較できる。そして、定義領域と参照領域が一部重複する場合には、ループが並列化不可と判定されてエラーメッセージ９１が表示される。
【０１８８】
多くの定義領域および参照領域は、連続領域になるかまたは規則的領域になると期待される。そのため、ループ内で個々のアドレスを比較して並列化可否を判定する可能性が低くなり、デバッグ用のオブジェクトコードにおいてもループを並列化できる可能性が高くなる。その結果、デバッグ用のオブジェクトコードの実行時間を短縮できる。また、アクセスされた領域のアドレスを網羅的に比較しなくてもよく、並列計算装置１００の負荷を軽減できる。このように、ループの並列化に関するソースコードの誤り（並列化不可のループに対して並列化が指示されていること）を効率的に検出できる。
【０１８９】
なお、前述のように、第１の実施の形態の情報処理は、並列計算装置１０にプログラムを実行させることで実現できる。第２の実施の形態の情報処理は、コンパイル装置２０にプログラムを実行させることで実現できる。第３の実施の形態の情報処理は、並列計算装置１００およびコンパイル装置２００にプログラムを実行させることで実現できる。
【０１９０】
プログラムは、コンピュータ読み取り可能な記録媒体（例えば、記録媒体１１３，２１３）に記録しておくことができる。記録媒体として、例えば、磁気ディスク、光ディスク、光磁気ディスク、半導体メモリなどを使用できる。磁気ディスクには、ＦＤおよびＨＤＤが含まれる。光ディスクには、ＣＤ、ＣＤ−Ｒ（Recordable）／ＲＷ（Rewritable）、ＤＶＤおよびＤＶＤ−Ｒ／ＲＷが含まれる。プログラムは、可搬型の記録媒体に記録されて配布されることがある。その場合、可搬型の記録媒体からＨＤＤなどの他の記録媒体（例えば、ＨＤＤ１０３，２０３）にプログラムをコピーして実行してもよい。
【符号の説明】
【０１９１】
１０  並列計算装置
１１，２１  記憶部
１２  演算部
１３，２３，２４  コード
１３ａ，２３ａ  ループ
１３ｂ，２３ｂ  配列
１３ｃ，１３ｄ，２３ｃ，２３ｄ  インデックス
１４ａ，１４ｂ，２４ｂ，２４ｃ  範囲
１５，２５  警告
２０  コンパイル装置
２２  変換部
２４ａ  検査処理
【図１】
2016224812.tif 000003
【図２】
2016224812.tif 000004
【図３】
2016224812.tif 000005
【図４】
2016224812.tif 000006
【図５】
2016224812.tif 000007
【図６】
2016224812.tif 000008
【図７】
2016224812.tif 000009
【図８】
2016224812.tif 000010
【図９】
2016224812.tif 000011
【図１０】
2016224812.tif 000012
【図１１】
2016224812.tif 000013
【図１２】
2016224812.tif 000014
【図１３】
2016224812.tif 000015
【図１４】
2016224812.tif 000016
【図１５】
2016224812.tif 000017
【図１６】
2016224812.tif 000018
【図１７】
2016224812.tif 000019
【図１８】
2016224812.tif 000020
【図１９】
2016224812.tif 000021
【図２０】
2016224812.tif 000022
【図２１】
2016224812.tif 000023
【図２２】
2016224812.tif 000024
【図２３】
2016224812.tif 000025
【図２４】
2016224812.tif 000026
【図２５】
2016224812.tif 000027
【図２６】
2016224812.tif 000028
【図２７】
2016224812.tif 000029
【図２８】
2016224812.tif 000030