(57)【特許請求の範囲】
【請求項１】
ループを含み逐次実行される変換対象プログラムと、該ループ内の処理を複数の処理に分割することを示すループ分割情報と、該複数の処理のうち該ループの終了制御処理を含む第１の処理を示す終了制御情報と、該複数の処理のうち該ループに後続する処理において参照されるデータを変更する変更処理を行う第２の処理を示す変更情報とを入力する入力部と、
前記ループ分割情報に従い、前記ループを前記複数の処理に分割し、該ループが分割された該複数の処理から、複数のコアまたはプロセッサを有する計算機上または複数の計算機上で動作する並列化プログラムを作成するループ並列化部と
を備え、
前記ループ並列化部は、前記終了制御情報および前記変更情報に基づき、
前記変換対象プログラム上で前記第２の処理が前記第１の処理の後続の処理である場合は、該第２の処理がループ反復回数（ｎ−１）回目（ｎは２以上の整数）の実行で終了するか否かの判定を行い、前記変換対象プログラム上で前記第２の処理が前記第１の処理の先行処理である場合は、該第２の処理がループ反復回数ｎ回目の実行で終了するか否かの判定を行い、該判定の結果を前記第２の処理に通知するための判定処理を、前記第１の処理に対して挿入し、
該判定処理により通知された該判定の結果により前記第２の処理の実行を制御するための制御処理を、前記第２の処理に挿入する
ことを特徴とするプログラム並列化装置。
【請求項２】
前記ループ分割情報は、
前記ループを、前記第１の処理と、前記第２の処理と、該ループ内で参照されるデータのみを扱う第３の処理とに分割することを示し、
前記ループ並列化部は、
前記変換対象プログラム上で前記第３の処理が前記第１の処理の後続の処理である場合は、該第３の処理の、反復回数（ｎ−１）回目までの実行を保証し、該（ｎ−１）回目以降の反復回数の実行の処理を終了するか否かの判定を行い、前記変換対象プログラム上で前記第３の処理が前記第１の処理の先行の処理である場合は、該第３の処理の少なくとも反復回数ｎ回目までの実行を保証し、該ｎ回目以降の反復回数の実行の処理を終了するか否かの判定を行い、該判定の結果を前記第３の処理に通知するための判定処理を、前記第１の処理に対して挿入し、
該判定処理により通知された該判定の結果により前記第３の処理の実行を制御するための制御処理を、前記第３の処理に挿入する
ことを特徴とする請求項１に記載のプログラム並列化装置。
【請求項３】
前記ループ並列化部による並列化プログラムの作成に先立って、前記変換対象プログラムを前記終了制御情報に基づき変換するループ変換部をさらに有し、
前記ループ変換部は、
前記ループの終了制御処理が該ループの内部で行われていない場合に、
該ループを、該ループの終了制御処理を行うための条件文が内部に挿入され、該条件文による条件を満たした場合に終了制御を行うループに変換する
ことを特徴とする請求項１または請求項２に記載のプログラム並列化装置。
【請求項４】
前記ループ変換部は、
前記ループの条件文に該ループの終了制御処理が含まれる場合に、
該ループを、該ループの終了制御処理を行うための条件文を内包し、反復回数が規定されないループに変換する
ことを特徴とする請求項３に記載のプログラム並列化装置。
【請求項５】
前記ループ変換部は、
前記ループの全体が含まれる例外処理が設定されている場合に、
該ループを、該ループ内の例外が発生する可能性のある処理に対して、例外を検出するための構文を設定し、該構文により例外が検出された場合に、処理を抜けるループに変換する
ことを特徴とする請求項３に記載のプログラム並列化装置。
【請求項６】
前記終了制御情報は、
前記第１の処理で終了制御命令がループの条件文として記述されていることを示す第１の終了処理情報と、
前記第１の処理で条件を満たした場合にループを含む関数を終了することを示す第２の終了処理情報と、
前記第１の処理で条件を満たした場合にループ外の指定部分に処理を飛ばすことを示す第３の終了処理情報と、
前記第１の処理で条件を満たしたループ反復回数ｍ回目（ｍは１以上の整数）の処理を終了し、ループ反復回数（ｍ＋１）回目の処理を実行することを示す第４の終了制御情報と
のうち何れか１である
ことを特徴とする請求項１乃至請求項５の何れか１項に記載のプログラム並列化装置。
【請求項７】
前記ループ並列化部は、
前記第１の処理において前記終了制御処理を実行する条件を満たしたことを示す第１のデータと、前記終了制御処理を含む前記第１の処理の反復回数を示す第２のデータとを有するデータ構造を持つ前記並列化プログラムを出力し、
前記ループ並列化部が出力する前記並列化プログラムは、
前記ループ分割情報に従い分割された各処理が、複数のコアまたはプロセッサを有する計算機上または複数の計算機上それぞれでスレッドとして動作し、
複数の前記スレッドは、計算機に、ループが終了したか否かと前記反復回数とを前記データ構造を参照して取得させるための第１のスレッドと、計算機に、前記データ構造を更新させるための第２のスレッドとを含む
ことを特徴とする請求項１乃至請求項６の何れか１項に記載のプログラム並列化装置。
【請求項８】
プログラム並列化方法をコンピュータに実行させるためのプログラムであって、
前記プログラム並列化方法は、
ループを含み逐次実行される変換対象プログラムと、該ループ内の処理を複数の処理に分割することを示すループ分割情報と、該複数の処理のうち該ループの終了制御処理を含む第１の処理を示す終了制御情報と、該複数の処理のうち該ループに後続する処理において参照されるデータを変更する変更処理を行う第２の処理を示す変更情報とを入力する入力ステップと、
前記ループ分割情報に従い、前記ループを前記複数の処理に分割し、該ループが分割された該複数の処理から、複数のコアまたはプロセッサを有する計算機上または複数の計算機上で動作する並列化プログラムを作成するループ並列化ステップと
を備え、
前記ループ並列化ステップは、前記終了制御情報および前記変更情報に基づき、
前記変換対象プログラム上で前記第２の処理が前記第１の処理の後続の処理である場合は、該第２の処理がループ反復回数（ｎ−１）回目（ｎは２以上の整数）の実行で終了するか否かの判定を行い、前記変換対象プログラム上で前記第２の処理が前記第１の処理の先行処理である場合は、該第２の処理がループ反復回数ｎ回目の実行で終了するか否かの判定を行い、該判定の結果を前記第２の処理に通知するための判定処理を、前記第１の処理に対して挿入し、
該判定処理により通知された該判定の結果により前記第２の処理の実行を制御するための制御処理を、前記第２の処理に挿入する、
プログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明の実施形態は、プログラム並列化装置およびプログラムに関する。
【背景技術】
【０００２】
逐次計算機用のプログラム（以下、逐次プログラムと呼ぶ）を、複数のコアまたプロセッサにより並列的に処理が可能なように並列化する技術が知られている。この逐次プログラムの並列化を行う場合、プログラムの中で計算時間の多くを占めているループを並列化することが一般的に行われる。ループの並列化については、従来から様々な手法が開発されている一方で、未だに並列化が困難なループも存在する。このような並列化が困難なループの１つとして、実行前にループの反復回数が不明なループが挙げられる。
【０００３】
従来、実行前にループの反復回数が不明なループを含むプログラムの並列化を行う場合、ループ終了後に利用されるデータの値を、ロールバックという手法を用いて保証することで並列化を行う技術がある。このロールバックを用いた技術では、ループ終了後に利用されるデータを各スレッドの実行毎に保存しておき、ループが終了する際にこの保存されたデータを呼び出すことにより、データの値を保証している。これにより、逐次プログラムを並列化して実行した場合に、並列化後のプログラムの実行結果が逐次プログラムの実行結果と異なることを回避することができる。
【先行技術文献】
【特許文献】
【０００４】
【特許文献１】特開平１１−１２０００３号公報
【発明の概要】
【発明が解決しようとする課題】
【０００５】
しかしながら、ロールバックにおいては、ループ終了後に利用されるデータを保存しておくためのメモリ領域を確保する必要があり、メモリが圧迫されてしまう。また、従来のロールバック技術によれば、必要なデータの保存やループ終了の検知、他のスレッドへの通知、保存されているデータの中から正しい値を読み出し、データを置き換えるといった操作が必要となり、制御が複雑になってしまう。
【０００６】
本発明の一実施形態によれば、大量のメモリ資源を必要とすること無く、実行前にループの反復回数が不明のループを含むプログラムコードを並列化することを目的とする。
【課題を解決するための手段】
【０００７】
実施の形態のプログラム並列化装置は、入力部とループ並列化部とを備える。入力部は、ループを含み逐次実行される変換対象プログラムと、ループ内の処理を複数の処理に分割することを示すループ分割情報と、複数の処理のうちループの終了制御処理を含む第１の処理を示す終了制御情報と、複数の処理のうちループに後続する処理において参照されるデータを変更する変更処理を行う第２の処理を示す変更情報とを入力する。ループ並列化部は、ループ分割情報に従い、ループを複数の処理に分割し、ループが分割された複数の処理から、複数のコアまたはプロセッサを有する計算機上または複数の計算機上で動作する並列化プログラムを作成する。ループ並列化部は、終了制御情報および変更情報に基づき、変換対象プログラム上で第２の処理が第１の処理の後続の処理である場合は、第２の処理がループ反復回数（ｎ−１）回目（ｎは２以上の整数）の実行で終了するか否かの判定を行い、変換対象プログラム上で第２の処理が第１の処理の先行処理である場合は、第２の処理がループ反復回数ｎ回目の実行で終了するか否かの判定を行い、判定の結果を第２の処理に通知するための判定処理を、第１の処理に対して挿入し、判定処理により通知された判定の結果により第２の処理の実行を制御するための制御処理を、第２の処理に挿入する。
【図面の簡単な説明】
【０００８】
【図１】実施形態のプログラム並列化装置を含むシステムの機能ブロック図。
【図２】プログラム並列化処理の例を概略的に示すフローチャート。
【図３】プログラム並列化部の機能を示す一例の機能ブロック図。
【図４】プログラム並列化処理を示す一例のフローチャート。
【図５】逐次プログラムの例を示す図。
【図６】プログラム解析部に係る、逐次プログラム以外の情報の例を示す図。
【図７】ループの条件文として終了制御処理が記述された例を示す図。
【図８】ループの全体が含まれる例外処理が記述されている例を示す図。
【図９】ループの並列化処理をより詳細に示す一例のフローチャート。
【図１０】中間並列化プログラムを構成するコードの例を示す図。
【図１１】ループ制御に用いるデータ構造と関数の例を説明するための図。
【図１２】終了処理を持つスレッドに対する処理の例を示すフローチャート。
【図１３】ループに後続する処理で参照されるデータを変更するスレッドに対する処理を示すフローチャート。
【図１４】その他のスレッドに対する処理の例を示すフローチャート。
【図１５】returnが終了制御の逐次プログラムの変換を説明するための図。
【図１６】gotoが終了制御の逐次プログラムの変換を説明するための図。
【図１７】continueが終了制御である逐次プログラムの例を示す図。
【図１８】continueが終了制御である逐次プログラムの変換を説明するための図。
【図１９】データ依存を保証する処理を含む並列化プログラムを構成するコードの例を示す図。
【図２０】並列化した３のスレッド間における依存関係の例を示す図。
【図２１】並列化されたループを実行した結果の例を示す図。
【図２２】比較例による並列化プログラムの制御例を示すフローチャート。
【図２３】実施形態によるプログラム並列化装置を実現可能な構成を示すブロック図。
【発明を実施するための形態】
【０００９】
図１は、実施の形態によるプログラム並列化装置を含むプログラム並列化システムの機能を説明するための一例の機能ブロック図である。このプログラム並列化システムは、プログラム解析部１０１と、プログラム並列化装置に対応するプログラム並列化部１０２と、プログラム変換部１０３とを備える。プログラム解析部１０１は、入力された逐次プログラム１１０を解析し、解析結果として終了制御情報１２０、変更情報１２１およびデータ依存情報１２２を出力する。なお、逐次プログラム１１０は、各指示が一列の時系列上で逐次的に実行可能に記述されたプログラムをいうものとする。
【００１０】
なお、ここでは、プログラム並列化装置がプログラム並列化部１０２に対応しているように説明しているが、これはこの例に限定されない。例えば、プログラム並列化装置は、プログラム並列化部１０２に加えてプログラム変換部１０３を備えていてもよい。さらに、プログラム並列化装置は、プログラム解析部１０１、プログラム並列化部１０２およびプログラム変換部１０３を備えていてもよい。
【００１１】
図２は、図１のプログラム並列化システムによるプログラム並列化処理の例を概略的に示すフローチャートである。図２のフローチャートの実行に先立って、例えばプログラム並列化システムの外部から、並列化プログラムへの変換対象である逐次プログラム１１０と、当該逐次プログラム１１０に含まれるループをどのような処理単位に分割するのかを示すループ分割情報１３０とが入力される。
【００１２】
最初のステップＳ１００で、プログラム解析部１０１は、それぞれ入力された逐次プログラム１１０およびループ分割情報１３０に基づき、当該逐次プログラム１１０を解析し、終了制御情報１２０、変更情報１２１およびデータ依存情報１２２を出力する。終了制御情報１２０は、プログラム中のどの処理がどのような形でループを終了させるのかを示す。変更情報１２１は、ループ終了後に利用されるデータを変更するのは、プログラム中のどの処理なのかを示す。また、データ依存情報１２２は、処理を分割した際に複数の処理で利用するデータの依存関係を示す。
【００１３】
次のステップＳ１０１で、プログラム並列化部１０２は、ステップＳ１００でプログラム解析部１０１から出力された終了制御情報１２０および変更情報１２１と、それぞれ入力された逐次プログラム１１０およびループ分割情報１３０とに基づき、当該逐次プログラム１１０に対して並列化処理を行い、中間並列化プログラム１３１を出力する。
【００１４】
次のステップＳ１０２で、プログラム変換部１０３は、ステップＳ１０１で出力された中間並列化プログラム１３１と、ステップＳ１００でプログラム解析部１０１から出力されたデータ依存情報１２２とに基づき、データの依存関係を保証した最終的な並列化プログラム１４０を作成し、出力する。
【００１５】
図３は、プログラム並列化部１０２の機能を示す一例の機能ブロック図である。プログラム並列化部１０２は、入力部２０１、ループ変換部２０２、ループ並列化部２０３および出力部２０４を備える。
【００１６】
図４は、プログラム並列化部１０２によるプログラム並列化処理を示す一例のフローチャートである。先ず、ステップＳ１１０で、入力部２０１は、逐次プログラム１１０、ループ分割情報１３０、終了制御情報１２０および変更情報１２１を入力する。次のステップＳ１１１で、ループ変換部２０２は、終了制御情報１２０に基づきループの終了制御がループの内部処理以外で実現されているか否かを判定する。その結果、ループ変換部２０２は、ループの内部処理以外で終了制御が実現されているループに限って、ステップＳ１１２で、ループの内部処理による終了制御が行われるように変換し、処理をステップＳ１１３に移行させる。終了制御がループの内部処理で行われていると判定した場合には、そのまま処理をステップＳ１１３に移行させる。
【００１７】
ステップＳ１１３で、ループ並列化部２０３は、ループ分割情報１３０に従い逐次プログラム１１０のループを各処理に分割し、分割された各処理を並列に実行できる形に変換する。例えば、マルチコアの各コアで実行することが可能となるスレッドやプロセスといった形に変換する。変換する形式はこれに限らず、並列化プログラム１４０を動作させる環境によって独自に用意されている並列化形式でもよい。さらに、ループ並列化部２０３は、ステップＳ１１０で入力部２０１に対して入力された各情報に基づき、ループが分割された各処理にループ終了時の処理を追加し、中間並列化プログラム１３１を生成する。そして、次のステップＳ１１４で、出力部２０４は、中間並列化プログラム１３１を出力する。
【００１８】
次に、本実施形態によるプログラム並列化処理について、典型的なソースコードを用いてより具体的に説明する。以下では、プログラム並列化システムが上述した図１の構成であり、プログラム並列化システム内のプログラム並列化部１０２が上述した図３の構成である場合を例にとって説明を行う。
【００１９】
なお、実施形態はこの例に限られず、例えば、図１および図３に例示する複数の機能ブロックが協調しながら動作を行う構成であってもよいし、一部の機能ブロックの順番を入れ替えた構成であってもよい。また、図１および図３に例示する構成のうち、ある機能ブロックを他の機能ブロックに分割することもできる。さらには、これら３つの形態を組み合わせた構成によりプログラム並列化システムを構成することも可能である。さらにまた、図１および図３に例示する複数の機能ブロックのうち１または複数を、複数のモジュールに分割してプログラム並列化システムを構成することもできる。
【００２０】
先ず、プログラム解析部１０１の機能について説明する。図１を参照し、プログラム解析部１０１は、既に述べたように、逐次プログラム１１０およびループ分割情報１３０に基づき逐次プログラム１１０を解析し、終了制御情報１２０、変更情報１２１およびデータ依存情報１２２を出力する。逐次プログラム１１０は、例えば、Ｃ言語やＪａｖａ（登録商標）言語のようなプログラミング言語を用いて記述される。これに限らず、逐次プログラム１１０は、特定の処理装置に独自のプログラミング言語を用いて記述されていてもよい。逐次プログラム１１０は、１つのファイルに全てのソースコードが格納されて提供されてもよいし、ソースコードが分割されて複数のファイルに格納されて提供されてもよい。
【００２１】
図５は、逐次プログラム１１０の例を示す。この例では、プログラム並列化システムによってコードの一部が変更される部分のソースコードのみが図５に示されているが、プログラム解析部１０１には、アプリケーションを動作させるために必要なソースコード全てを入力してもよい。多くのソースコードを入力した場合、解析時間は長くなるが、その分データ依存関係などの解析精度は向上する。
【００２２】
なお、この図５および以下の同様のプログラム例を示す図において、特に記載のない限り、各行の先頭の２桁の数字は説明のための行番号を示し、続くコロン（：）でソースコード本体と区別されている。また、本実施形態の中で例示される各プログラムおよびコードは、プログラミング言語として一般的に用いられるＣ言語の記法を模した疑似コードである。
【００２３】
図５の例では、逐次プログラム１１０を記述するコード５０１において、６行目から１２行目までが、for文によるループを構成している。また、ループ中、７行目でループ変数iによる関数処理がなされ、８行目で７行目の結果に基づく関数処理がなされる。さらに、９行目では、８行目の結果に基づく判定処理がなされ、判定結果に応じて１０行目でループに対する終了制御処理がなされる。また、ループ外の１３行目は、他の関数に返すための戻り値が示される。
【００２４】
図６は、プログラム解析部１０１に係る、逐次プログラム１１０以外の情報の例を示す。図６（ａ）は、ループ分割情報１３０の例を示す。図６（ｂ）および図６（ｃ）は、それぞれ終了制御情報１２０および変更情報１２１の例を示す。また、図６（ｄ）は、データ依存情報１２２の例を示す。
【００２５】
図１では、ループ分割情報１３０は、ユーザがテキストエディタなどを用いて直接的に記述してプログラム並列化部１０２に対して入力するように示されているが、これはこの例に限定されない。例えば、プログラム解析部１０１により逐次プログラム１１０を解析して並列化に適したループを探索し、並列化が容易な分割方法を決定することでループ分割情報１３０を出力してもよい。また、プログラム変換部１０１においてループ分割情報１３０をユーザにＧＵＩ(Graphical  User  Interface)などを通じて提示し、確認および修正を行った情報を出力してもよい。なお、逐次プログラム１１０のソースコードから、ループ分割情報１３０を出力する方法は、既存の、コンパイラなどでプログラムの構文解析を行う技術を応用することで実現できる。
【００２６】
また、図１では、終了制御情報１２０、変更情報１２１およびデータ依存情報１２２は、プログラム解析部１０１が逐次プログラム１１０を解析して出力するようにしている。なお、逐次プログラム１１０のソースコードから、終了制御情報１２０、変更情報１２１およびデータ依存情報１２２を出力する方法は、既存の、コンパイラなどでプログラムの構文解析を行う技術を応用することで実現できる。
【００２７】
終了制御情報１２０、変更情報１２１およびデータ依存情報１２２を生成するには、例えばこれらの情報のうち１つまたは複数を、ユーザがテキストエディタなどを用いて直接的に記述してプログラム並列化部１０２に対して入力するようにしてもよい。また、プログラム変換部１０１において終了制御情報１２０、変更情報１２１およびデータ依存情報１２２をユーザにＧＵＩなどを通じて提示し、確認および修正を行った情報を出力してもよい。
【００２８】
また、ループ分割情報１３０、終了制御情報１２０、変更情報１２１およびデータ依存情報１２２は、プログラム並列化部１０２およびプログラム変換部１０３が必要とする情報を含んでいれば、作成方法は問わない。例えば、並列化コンパイラなど、他の装置向けに作成されたプログラム解析部１１０で作成したものであっても、他の装置を本実施形態によるプログラム並列化部１０２向けに改造したものであってもよい。また、プログラム解析部１０１によって生成された終了制御情報１２０、変更情報１２１およびデータ依存情報１２２を、さらにユーザがテキストエディタなどを用いて修正してプログラム並列化部１０２に入力することも考えられる。また、ループ分割情報１３０、終了制御情報１２０、変更情報１２１およびデータ依存情報１２２はテキストデータではなく、バイナリデータや、プログラム並列化システムや他の装置向けに独自に定義された中間データ形式であってもよい。
【００２９】
さらに、ループ分割情報１３０、終了制御情報１２０、変更情報１２１およびデータ依存情報１２２は、それぞれ別個のファイルに格納されて提供されてもよいし、纏めて１つあるいは複数のファイルに格納されて提供されてもよい。ループ分割情報１３０、終了制御情報１２０、変更情報１２１およびデータ依存情報１２２を混在させてファイルに格納して提供することも考えられる。
【００３０】
ループ分割情報１３０について説明する。ループ分割情報１３０は、逐次プログラム１１０中の並列化の対象となるループの内部処理を、並列化に適した処理単位に分割するための情報を含む。図６（ａ）の例では、情報６０１の第１行目の記述「7:thread＿1」が、逐次プログラム１１０のコード５０１における７行目を「thread＿1」と呼ばれる処理に分割し、第２行目の記述「8:thread＿2」が、当該コード５０１における８行目を「thread＿2」と呼ばれる処理に分割し、第３行目の記述「9-11:thread＿3」が、当該コード５０１の９行目から１１行目を「thread＿3」と呼ばれる処理に分割することを示す。
【００３１】
この例では単一のファイル内のプログラムを行数で指定しているが、指定方法はこれに限らない。複数ファイル内のプログラムを指定するために、プログラムのファイル名などを行数の前に記述してもよい。また、逐次プログラム１１０中に分割する部分を直接指定してもよいし、その指定した部分にラベルを付け、これをループ分割情報１３０にそのラベルで指定してもよい。このように、並列化するループの内部処理をどのように分割するかを指定できれば、ループ分割情報１３０における構文の文法は問わない。
【００３２】
なお、以下では、適宜、「thread＿1」と呼ばれる処理を実行するスレッドをスレッドthread＿1、「thread＿2」と呼ばれる処理を実行するスレッドをスレッドthread＿2、「thread＿3」と呼ばれる処理を実行するスレッドをスレッドthread＿3と称する。
【００３３】
終了制御情報１２０について説明する。終了制御情報１２０は、ループ分割情報１３０によって分割された各処理の中で、ループの終了制御を行う処理を指定する。図６（ｂ）の例では、情報６０２の記述「End:thread＿3」が、図６（ａ）に例示されるループ分割情報１３０において処理「thread＿3」の中でループの終了制御が行われていることを示す。
【００３４】
また、ループの終了制御を行う構文がある１つの処理の中に複数存在する場合、例えば、処理「thread＿3」の中に２つの終了制御が存在する際には「End:thread＿3:2」のように記述することができる。この例では、ループ分割情報１３０によって設定された処理名を用いて終了制御処理を指定しているが、指定方法はこれに限らない。ループ分割情報１３０のように、プログラム中の行数で終了制御コードを指定し、プログラム並列化部１０２にてループ分割情報１３０の情報と組み合わせることでループの終了制御を行う処理を指定してもよい。また、逐次プログラム１１０中に終了制御コードを直接指定してもよいし、その指定した部分にラベルを付け、これを終了制御情報１２０にそのラベルと終了制御の数で指定してもよい。また、この例では終了制御情報１２０によって指定されたスレッドは１つであったが、複数あっても構わない。このように、終了制御を行う部分が幾つ存在し、それをどの処理が行うのかを指定できれば、終了制御情報１２０における構文の文法は問わない。
【００３５】
変更情報１２１について説明する。変更情報１２１は、ループ分割情報１３０によって分割された各処理の中で、ループ終了後に利用されるデータを変更している処理を指定する。図６（ｃ）の例では、情報６０３の記述「Effect:thread＿2」は、図６（ａ）に例示されるループ分割情報１３０において処理「thread＿2」の中で、ループ終了後に利用されるデータを変更する処理が行われていることを示す。
【００３６】
この例では、ループ分割情報１３０によって設定された処理名を用いて変更処理を指定しているが、指定方法はこれに限らない。ループ分割情報１３０のように、プログラム中の行数でループ終了後に利用されるデータの変更コードを指定し、プログラム並列化部１０２にてループ分割情報１３０の情報と組み合わせることで、ループ終了後に利用されるデータを変更している処理を指定してもよい。また、逐次プログラム１１０中に変更処理コードを直接指定してもよいし、その指定した部分にラベルを付け、これを変更情報１２１にそのラベルで指定してもよい。このように、変更処理を行う部分をどの処理が行うのかを指定できれば、変更情報１２１における構文の文法は問わない。
【００３７】
なお、図６（ｃ）の情報６０３の例では、ループ終了後に利用されるデータを変更する処理を指定していたが、データを変更する処理を指定する代わりに、ループ終了後に利用されるデータを変更しない処理を、例えば記述「Noeffect：thread＿1」といったように指定してもよい。
【００３８】
データ依存情報１２２について説明する。データ依存情報１２２は、ループ分割情報１３０に基づきループを分割した際に分割された処理間で利用するデータの依存関係の情報を示す。図６（ｄ）の例では、情報６０４の記述「thread＿2:total->thread＿3:total」は、ループ分割情報１３０において処理「thread＿2」の中で変更される変数totalから、同じイタレーション回数の処理「thread＿3」で利用されるデータtotalに対してデータの依存関係があることを示す。
【００３９】
なお、上述の例では、同じイタレーション回数のスレッドにデータ依存関係が存在したが、異なるイタレーション回数のスレッドに対してデータ依存関係を設定することもできる。例えば、イタレーション回数[i]のスレッドthread＿2の変数totalが、次のイタレーション回数[i+1]のスレッドthread＿3の変数totalとして使われる場合、データ依存情報１２２を、「thread＿2[0]:total->thread＿3[1]:total」などと記述することで実現できる。
【００４０】
この例では、逐次プログラム１１０内の変数名によってデータ依存情報を指定しているが、指定方法はこれに限らない。ループ分割情報１３０のように、プログラム中の行数でデータ依存コードを指定し、プログラム並列化部１０２にてループ分割情報１３０の情報と組み合わせることで、ループ終了後に利用されるデータを変更している処理を指定してもよい。また、逐次プログラム１１０中にデータ依存コードを直接指定してもよいし、その指定した部分にラベルを付け、これをデータ依存情報１２１にそのラベルで指定してもよい。このように、データ依存処理を行う部分をどの処理が行うのかを指定できれば、データ依存情報１２１における構文の文法は問わない。
【００４１】
次に、プログラム並列化部１０２の機能について、図１および図３の機能ブロック図と、図４のフローチャートとを参照しながら説明する。プログラム並列化部１０２は、既に述べたように、逐次プログラム１１０、ループ分割情報１３０、終了制御情報１２０および変更情報１２１に基づき逐次プログラム１１０を並列化し、中間並列化プログラム１３１を出力する。先ず、図４のステップＳ１１０において、逐次プログラム１１０、ループ分割情報１３０、終了制御情報１２０および変更情報１２１が入力部２０１に対して入力され、ループ変換部２０２に供給される。
【００４２】
並列化対象とされる逐次プログラム１１０は、実行前に反復回数の不明なループを含むものとする。ここで、ループとは、プログラムを何らかの方式でコンパイルし、動作させる計算機用の機械語を生成した際に、同じ処理が繰り返されている部分のことを指す。例えば、Ｃ言語やＪａｖａ（登録商標）言語では、ループ処理は、for文やwhile文などを用いて記述できる。これに限らず、ループ処理は、再帰関数の呼び出しによっても記述できる。また、機械語でループ処理を直接的に記述することもできる。
【００４３】
このループによる繰り返し処理が一定回数ではなく、プログラムへの入力や実行環境などによって変化する場合、ループの反復回数を予め知ることができない。本プログラム並列化システムは、このような、プログラムの実行前にループの反復回数が不明なループを並列化するものである。このような条件を満たさないループを並列化対象とした場合、プログラム並列化部１０２は、ループを並列実行可能な形に分割する処理のみを行う。並列化するループは、逐次プログラム１１０の中で１つだけとは限らず、複数存在してもよい。また、並列化するループの内部に１つ以上のループが存在していてもよく、内部のループも並列化対象ループとしてもよい。その場合、上記の条件を満たすループと満たさないループが混在していてもよい。
【００４４】
なお、入力部２０１に対する逐次プログラム１１０や各情報の入力の方法として、例えば、一般的に行われている、ファイルシステムを用いる方法が考えられる。例えば、フレキシブルディスク、光ディスク、ハードディスクドライブ、装置に対して着脱可能な不揮発性半導体メモリなどの記憶媒体に逐次プログラム１１０や各情報を記憶させ、入力部２０１が、この記憶媒体からこれら逐次プログラム１１０や各情報を読み出す。
【００４５】
これに限らず、これら逐次プログラム１１０や各情報を、ネットワークなどを介して予めメモリに読み込ませ、このメモリから逐次プログラム１１０や各情報を入力部２０１に入力させてもよい。また、例えばプログラム並列化部１０２を実行させるためのソースコードやプロファイル情報に、これら逐次プログラム１１０や各情報を予め組み込んでおいてもよい。さらに、これら逐次プログラム１１０や各情報を、ＧＵＩなどを通じてユーザが直接的に入力部２０１に入力するようにもできる。さらにまた、プログラム解析部１０１とプログラム並列化部１０２とを１つのシステムとすることで、何らかの通信手段を用いてプログラム解析部１０１からプログラム並列化部１０２に対して直接的に情報を受け渡してもよい。
【００４６】
次に、図４のステップＳ１１１およびステップＳ１１２において、ループ変換部２０２は、入力部２０１に入力された逐次プログラム１１０とループ分割情報１３０とから、逐次プログラム１１０に含まれる、並列化対象となるループを並列化に適した形式に変換する。なお、逐次プログラム１１０のソースコードから、並列化対象となるループを検索する方法は、既存の、コンパイラなどでプログラムの構文解析を行う技術を応用することで実現できる。また、逐次プログラム１１０上に並列化対象となるループをユーザが指定したり、ループ分割情報１３０のような形で並列化対象ループを指定した情報をプログラム解析部１０１やプログラム並列化部１０２に入力してもよい。
【００４７】
図４のフローチャートのステップＳ１１１で既に説明したように、ループの変換は、ループの終了制御処理がループ内部の処理以外の形で実現されている場合に限り行われる。すなわち、ループの終了制御処理がループ内部で行われていない場合に、当該ループを、当該ループの終了制御処理を行うための条件文を内包し、この条件文による条件を満たした場合にループを終了する処理を含んだループに変換する。
【００４８】
より具体的な例を、図７および図８を用いて説明する。図７は、ループの条件文として終了制御を行う処理が記述された場合の例である。すなわち、図７（ａ）に例示されるコード７０１において、４行目から７行目が条件文whileによるループを構成する。条件文whileは、ループの先頭に置かれ処理がループ内部に移行するか否かの判断を行うもので、終了処理がループ内部の処理ではない。
【００４９】
このコード７０１の例では、ループの条件文を内部の処理としてループ内部に挿入し、ループ自体は無限ループすなわち反復回数を規定しないループに変換することで、ループ部分の並列化が可能且つ元の逐次プログラムと結果が等価な逐次プログラムへと変換する。図７（ｂ）は、コード７０１に含まれるループを並列化可能なループに変換した例を示す。図７（ｂ）のコード７０２において、ループをfor文を用いて無限ループとして構成すると共に、コード７０１におけるループの条件文whileを条件文ifに変換し、ループ内部に挿入している。この例では、for文を用いて無限ループを構成し、if文を用いて判定処理を行っているが、同様の処理を実現できれば、while文を用いても、アーキテクチャ特有の方法等を用いてもよい。
【００５０】
なお、ループの変換の要否は、例えば、プログラム解析部１０１によって静的に逐次プログラム１１０の解析を行い、解析結果に基づき確認する方法が考えられる。この場合、プログラム解析部１０１から出力される終了制御情報１２０に対して、終了制御を行う処理がループの条件文として記述されている、あるいは、例外処理を行うコードが含まれているという情報を持たせることで実現できる。コード７０１の場合、４行目の条件文whileが終了制御命令に該当するため、終了制御情報１２０は、図７（ｃ）に情報７０３の記述「4:End:Loop」として例示されるように、終了制御命令が４行目にループの条件文として記述されていることを示すような構成とされる。この終了制御情報１２０を受けて、ループ変換部２０２がループの変換を行う。
【００５１】
この場合の終了制御情報１２０についても、上述の通り必要な情報の受け渡しができる形式ならば文法などは問わない。また、ユーザがソースコードを解析し、ループ変換の要否をプログラム解析部１０１やループ分割情報１３０などを通じて、プログラム解析部１０１あるいはプログラム並列化部１０２に対して、直接的または出力された情報を修正することにより入力してもよい。
【００５２】
図８は、並列化対象となるループの全体が含まれる例外処理が記述されている場合の例である。なお、Ｃ言語には例外処理用の構文が用意されていないため、図８のコード例はＣ＋＋言語を模した疑似コードを用いている。
【００５３】
例外処理とは、プログラムの実行中に発生した例外に対して、特別な処理を行う機構をいう。すなわち、例外処理では、プログラムのある処理を実行中に何らかの異常が発生した場合に、その処理を中断して別の処理を行う。例えばＣ＋＋言語やＪａｖａ（登録商標）言語においては、例外処理構文におけるtry文により、例外が発生する可能性のあるコードを囲み、その内部でエラーが発生した場合は、throw文を用いて例外の発生を通知する。例外発生が通知された場合は、catch文の内部の処理を実行する。これにより、例外に対応した処理を行う。
【００５４】
図８（ａ）に例示されるコード８０１において、４行目にtry文が置かれ、try文の括弧の内部（５行目から８行目）に並列化対象のループが記述されている。また、このtry文の直後に、try文に対応するcatch文が記述されている。５行目〜８行目のループにおいて例外が発生した場合に、try文により例外がキャッチされて処理がループ外部のcatch文に移行するため、終了処理がループ内部の処理ではない。
【００５５】
このコード８０１の例のように、try文の括弧の内部に並列化対象のループが記述されている場合、ループ分割情報１３０に基づいて分割されたループ内部の各処理をそれぞれtry文の括弧で囲み、その後catch文が実行されるようにループを変換する。さらに、catch文に書かれていた処理の他に、catch文が発生したらループが終了するようにループを変換する。
【００５６】
図８（ｂ）は、コード８０１に含まれるループを並列化可能なループに変換した例を示す。図８（ｂ）のコード８０２において、ループ分割情報１３０に基づいて分割されるコード８０１におけるループ内部の各処理をそれぞれtry文の括弧で囲むと共に、各try文に対してそれぞれcatch文を記述する。コード８０２では、コード８０１の６行目の処理と７行目の処理をそれぞれループ分割情報１３０によって分割すると仮定している。より具体的には、コード８０２では、コード８０１におけるループ内部の６行目の処理に対してtry文および対応するcatch文が記述され（５行目〜１１行目）、コード８０１におけるループ内部の７行目の処理に対してtry文および対応するcatch文が記述される（１２行目〜１８行目）。
【００５７】
この場合、終了制御情報１２０は、図８（ｃ）の情報８０３の記述「End:exception」により、並列化対象となるループ全体が含まれるような例外処理が記述されていることを示すような構成とされる。この情報を受けて、ループ変換部２０２がループの変換を行う。この場合の終了制御情報１２０についても、上述の通り必要な情報の受け渡しができる形式ならば、文法などは問わない。また、ユーザがソースコードを解析し、ループ変換の要否をプログラム解析部１０１やループ分割情報１３０などを通じて、プログラム解析部１０１あるいはプログラム並列化部１０２に対して、直接的または出力された情報を修正することにより入力してもよい。
【００５８】
次に、図４のステップＳ１１３において、ループ並列化部２０３は、逐次プログラム１１０中の並列化対象となるループを、ループ分割情報１３０に基づき、各処理に分割する。さらに、ループ並列化部２０３は、分割された各処理を並列化可能な形式に変更する。本実施形態においてはスレッド形式に変更するが、上述の通り、プロセスなどの形式に変更してもよい。そして、終了制御情報１２０および変更情報１２１を用いて、ループ終了後に利用されるデータの値を保証するための処理を各スレッドに追加し、並列化を行う。
【００５９】
この例では、終了制御情報１２０は、図６（ｂ）で示した情報６０２とし、スレッドthread＿3が終了制御を含む。また、変更情報１２１は、図６（ｃ）で示した情報６０３とし、スレッドthread＿2がループ終了後に利用されるデータを変更することを示している。図５のコード５０１を参照すると、スレッドthread＿2は、ループ終了後に利用されるデータtotalの値を変更し、スレッドthread＿3は、コード「break」による終了制御が行われている。なお、終了制御の数や終了制御を持つスレッドの数は、１つに限定されない。
【００６０】
ループ並列化部２０３では、終了制御を持つスレッド、ループ終了後に利用されるデータの値を変更するスレッド、それ以外のスレッドの３種のスレッドに対し、それぞれ別の処理を追加する。この例では、ループ制御用の構造体を操作する処理をプログラム内に関数として追加し、この関数を呼び出す形で、ループ制御用の構造体の操作を実現しているが、これはこの例に限定されない。例えば、ループ制御用の構造体の操作処理をライブラリとして用意し、このライブラリから必要な処理を呼び出すようにしてもよい。また、ＦＩＦＯ（First  In  First  Out）やアーキテクチャが用意している専用命令を利用したスレッド間通信を用いてスレッド間で直接構造体のデータをやり取りすることで、ループ制御用の構造体の操作処理を実現してもよい。
【００６１】
図９は、図４のステップＳ１１３の処理をより詳細に示す一例のフローチャートである。ループ並列化部２０３は、先ず、ステップＳ１３０で、ループ分割情報１３０に基づき逐次プログラム１１０のループ内部の各処理を分割し、スレッド化する。次のステップＳ１３１で、ループ制御用の関数、ループ制御用の構造体を各スレッドから実行可能な状態で追加する。さらに、ループ制御用の構造体の初期化処理を追加する。次に、ステップＳ１３２で、ステップＳ１３０で作成された各スレッドに、ループの反復回数をカウントするための変数を追加する。次のステップＳ１３３で、ステップＳ１３０で作成されたスレッドのうち、終了制御を持つスレッドに対する処理を行う。
【００６２】
さらに、次のステップＳ１３４で、ステップＳ１３０で作成されたスレッドのうち、保証する必要のあるデータ、すなわち、ループ終了後に利用されるデータを変更するスレッドに対する処理が行われる。最後に、ステップＳ１３５で、その他すなわちステップＳ１３３およびステップＳ１３４で処理された以外のスレッドに対する処理が行われる。以上のようにして、最終的に、中間並列化プログラム１３１が作成される。
【００６３】
ステップＳ１３０の処理について、より詳細に説明する。図６（ａ）の情報６０１に示したように、ループ分割情報１３０には、分割を行う処理が指定されている。ステップＳ１３０で、ループ並列化部２０３は、この指定に従いループ内部の各処理を分割する。さらに、分割された各処理をスレッド形式に変更する。すなわち、ループ並列化部２０３は、逐次プログラム１１０およびループ分割情報１３０に基づき、例えばＣ言語の関数に準じた形式で各スレッド内部の処理をそれぞれ独立に記述し、逐次プログラム１１０の分割を行う。
【００６４】
より具体的には、ループ並列化部２０３は、情報６０１として例示されるループ分割情報１３０に従い、図５に例示されるコード５０１のうち、７行目をスレッドthread＿1、８行目をスレッドthread＿2、９行目〜１１行目をスレッドthread＿3に分割し、コード５０１のループ部分をそれぞれ独立した３のスレッドthread＿1、スレッドthread＿2およびスレッドthread＿3として記述する。
【００６５】
これらスレッドthread＿1、thread＿2およびthread＿3のうち、スレッドthread＿2は、ループ終了後に利用されるデータを変更するスレッドであり、スレッドthread＿3は、条件によりループから外に飛び出るスレッドである。スレッドthread＿1は、これら何れのタイプのスレッドにも該当しないスレッドである。なお、ループが分割されたスレッド数は、３に限られない。
【００６６】
また、ループの終了制御を持つスレッド、ループ終了後に利用されるデータを変更するスレッド、ならびに、これらのタイプに該当しないスレッドは、１つの入力プログラムに対し、それぞれ１つ以上存在する必要はなく、０であってもよい。各タイプに該当するスレッドが存在しない場合、それらのタイプ向けの処理は実行されない。さらに、ループの終了制御を持つスレッドが存在しない場合、プログラム並列化部１０２はループを並列実行可能な形式に変換する作業のみを行う。また、終了制御情報１２０で指定されている処理と変更情報１２１で指定されている処理は重複していてもよい。これにより、ループの終了制御を持つスレッドが複数存在している場合にも他の終了制御に対する制御処理を挿入することができる。
【００６７】
元のループ内には、各スレッドthread＿1、thread＿2およびthread＿3を呼び出すためのコードと、最後にスレッドの終了を待ち合わせるためのコードとを挿入し、元の処理をこのコードに置き換える。図１０と、上述した図５とを用いてより具体的に説明する。図１０は、逐次プログラム１１０に基づきループ並列化部２０３で生成される、中間並列化プログラム１３１を構成するコード１００１の例を示す。なお、図１０において、コード１００１は、このコード１００１に関する処理が終了し本実施形態の説明に必要な部分が完成した形態で示されている。
【００６８】
ループ並列化部２０３は、図５のコード５０１のループ開始行の直前、ループ内部およびループ終了行直後のうち何れかの位置に、図１０のコード１００１における７行目〜１２行目のコードを挿入する。このコード１００１における７行目〜１２行目のコードは、並列処理を行うことを示すものである。より具体的には、コード１００１における７行目のコード「fork(thread＿1)」は、スレッドthread＿1を生成し、処理を別のコアまたはプロセッサなどにより処理させることを示す。また、コード１００１における１０行目のコード「join(thread＿1)」は、スレッドthread＿1の処理が終了するまで待機状態となることを示す。つまり、この例では、各スレッドthread＿1、thread＿2およびthread＿3が複数のコアまたはプロセッサにより並列処理されることが示されている。
【００６９】
なお、逐次プログラム１１０におけるループのスレッド分割方法は、この方法に限定されない。ループのスレッドへの分割および並列化の方法は、変換された並列化プログラムを動作させるアーキテクチャや、システム、並列処理をどのように実現するかによって異なる。
【００７０】
例えば、Ｃ言語の関数に似た形式でスレッド内部の処理を独立に記述し、分割させる方法を用いることができる。Ｃ＋＋言語やＪａｖa（登録商標）言語のクラスのような形式でスレッド内部の処理を独立に記述し、分割させる方法を用いることもできる。また、分割させる処理をそれぞれ括弧「｛｝」で囲むことで分割する方法を用いることもできる。さらに、並列処理専用の特別な構文を持つアーキテクチャやプログラム言語を利用する場合、そうした構文を挿入することで分割や並列化を行う方法も考えられる。
【００７１】
さらに、本実施形態のように各スレッドを１回ずつ呼び出す形式ではなく、スレッドの呼び出し部分をループで囲み、複数回スレッドを呼び出すようなコードを記述し、スレッド本体にはループ部分を記述しないという方法も考えられる。さらにまた、アーキテクチャやプログラミング言語にスレッド呼び出し方法が規定されている場合、それに沿ったものにする必要がある。
【００７２】
本実施形態では、ループ内部の処理を単純に分割してスレッド化を行っている。これに限らず、ループのイタレーション回数に応じて分割を行うこともできる。例えば、ループを、ループのイタレーション回数が５０回目までと、それ以降とに分割する。この場合、プログラム解析部１０１では、分割された処理を別々の処理と見做して依存関係などの解析を行う。また、ループ内部の処理を分割する方法と、ループのイタレーション回数に応じて分割する方法とを組み合わせた分割方法も考えられる。
【００７３】
次に、図９のステップＳ１３１による、ループ制御用の関数、データ構造および初期化処理を追加する処理について、より詳細に説明する。先ず、図１１を用いて、ループ制御に用いるデータ構造および関数の例について説明する。この図１１に例示されるコード１１０１と、上述の図１０に例示されるコード１００１とから、中間並列化プログラム１３１が構成される。なお、図１１において、コード１１０１は、このコード１１０１に関する処理が終了し本実施形態の説明に必要な部分が完成した形態で示されている。
【００７４】
図１１のコード１１０１において、１行目から４行目は、ループが終了したか否かをチェックするためのデータcancel＿stateのデータ構造体を定義するためのコードである。２行目のコード「char  canceled」は、ループを終了したか否かを示す変数canceledを定義するためのコードである。変数canceledは、「１」でループが終了したことを示し、「０」でループの実行が継続されていることを示す。３行目のコード「unsigned  long  count」は、ループの終了制御を含む最内周のループのカウント回数を示す変数countを定義するためのコードである。すなわち、このように構造が定義されたデータcancel＿stateを用いることで、ループが何回目で終了したかを知ることができ、複数のコアでそれぞれループの終了制御によってループが終了した際のループの進み方を判定できる。
【００７５】
コード１１０１において、６行目のコード「struct  cancel＿state  cansel[NUM＿CONT＿STAT]」は、上述のデータ構造「cancel＿state」の実体を用意するためのコードである。値「NUM＿CONT＿STAT」は、並列化対象ループ中に存在する終了制御処理の数を示しており、終了制御処理の数の分だけデータ構造「cancel＿state」が用意される。
【００７６】
コード１１０１において、８行目から１３行目のコードは、変数canceledおよび変数countを初期化する関数である。コード１１０１の１５行目から２０行目のコードは、ループの終了制御処理を持つスレッドに置かれる関数であって、ループが終了しているか否かを示す値「canceled」と、各終了制御処理固有のＩＤを示す変数「cancel＿ID」とが引数とされる。１６行目は、変数canceledを更新するためのコードである。また、１７行目のif文により、ループが終了していない場合に１８行目で変数countを１だけインクリメントする。
【００７７】
コード１１０１において、２２行目から３４行目のコードは、ループ終了後に利用されるデータを変更するスレッド（この例ではスレッドthread＿2）のループ回数が、ループの終了制御を持つスレッド（この例ではスレッドthread＿3）のループ回数を超えていないかどうかをチェックする関数である。また、この関数は、ループ終了後に利用されるデータを変更しないスレッド（この例ではスレッドthread＿1）のループ回数が、ループの終了制御を持つスレッドのループ回数を超えていないか否かをチェックする関数でもある。
【００７８】
２２行目の変数countは、スレッドの現在のループ回数を示す引数である。同行の変数effectは、そのスレッドがループ終了後に利用されるデータ、すなわち、ループの外側で保証しなければいけないデータを変更するスレッドか否かを示す引数である。変数effectが値「１」で変更するスレッド、値「０」で変更しないスレッドをそれぞれ示す。同行の変数cancel＿IDは、各終了制御処理固有のＩＤを示す引数である。
【００７９】
コード１１０１において、２３行目のif文および２４行目から２６行目のwhile文は、ループ終了後に利用されるデータを変更するスレッドにおいて、処理したループの回数が、ループの終了制御を持つスレッドのループ回数と等しくなるまで待機することを示す。
【００８０】
上述した図９のステップＳ１３２において、ループ回数を保存するための変数を更新するための構文は、ループの終了制御が行われるか否かが決定された後の部分に挿入される。このため、逐次プログラム１１０上でループ終了後に利用されるデータを変更するスレッドが終了制御処理を持つスレッドに先行する場合、コード１１０１の２４行目から２６行目までのwhile文により、終了制御を持つスレッドのループ反復回数がｎ回目とすると、ループ終了後に利用されるデータを変更するスレッドも、ループ反復回数ｎ回目の処理までの実行が許可される。そうでない場合には（ｎ−１）回目の処理までの実行が許可される。
【００８１】
２７行目のif文は、ループが終了したか否かを実際にチェックする。３０行目のif文は、保証しなければならないデータを変更しないスレッドに対してループが終了したか否かをチェックする。このスレッドの場合、終了制御を持つスレッドとの依存関係は存在しないため、待機処理が必要ない。これにより、逐次プログラム１１０上でループ終了後に利用されるデータを変更しないスレッドが終了制御処理を持つスレッドに先行する場合、コード１１０１の３０行目のif文により、終了制御を持つスレッドのループ反復回数がｎ回目とすると、ループ終了後に利用されるデータを変更するスレッドもループ反復回数ｎ回目の処理までの実行が保障される。そうでない場合には（ｎ−１）回目の処理までの実行が保障される。何れの場合も、ループが終了した場合には、値「１」が返される。
【００８２】
次に、逐次プログラム１１０にループ制御用関数とデータ構造を追加する方法について説明する。先ず、図１１のコード１１０１を、図９のステップＳ１３０によって作成された各スレッドから実行可能な箇所に挿入する。上述の通り、ループ制御用の処理やデータ構造を、図１１のコード１１０１のように関数やデータ構造として用意していない場合は、用意されている処理とデータ構造とを図９のステップＳ１３０によって作成された各スレッドから利用可能な形態にする。また、図１１のコード１１０１における６行目および９行目の値「NUM＿CONT＿STAT」は、並列化対象ループ中に存在する終了制御処理の数を示しており、終了制御情報１２０からこれを求め、実数を代入する。
【００８３】
さらに、ループ並列化部２０３は、ループ制御用のデータ構造のデータを初期化する処理を、図５のコード５０１のループ部分に挿入する。より具体的には、コード１００１に対し、図１０のコード１００１における６行目に例示されるように、コード「reset＿cancel＿state()」が挿入される。挿入する場所は、ステップＳ１３０にて挿入された並列処理用のコード（コード１００１における７行目〜１２行目のコード）より前であればよい。
【００８４】
なお、この例では、終了制御を持つスレッドがスレッドthread＿3の１つだけなので、ループ制御用のデータ構造も１つ宣言すればよい。一方、終了制御を持つスレッドが２つ以上存在する場合は、終了制御毎に割り当てられる固有ＩＤを使って終了制御毎に処理を行えるようにすることで、終了制御の数が増えても対応できる。また、配列形式ではなく、ループ制御用の変数自体を複数宣言するようにしたり、リスト構造などのデータ構造などを用いて情報を保持してもよい。
【００８５】
次に、図９のステップＳ１３２による、ループの反復回数を保存するための変数を図９のステップＳ１３０によって作成された各スレッドに追加する処理を行う。より具体的には、図１０のコード１００１に対して、コード１００１における１７行目および２８行目に示されるように、並列化対象となるループに対し、新たにループの反復回数をカウントする変数countを各スレッドに挿入する。変数countが挿入される位置は、ループよりも前であればよい。さらに、このカウンタをインクリメントする処理をコード１００１の２３行目および３４行目に挿入する。このカウンタインクリメント処理を挿入する位置は、あるイタレーションにおいて、ループの終了制御処理が実行されないことが確定する部分以降であり、且つ次のイタレーションの実行前の部分であればよい。また、終了制御を持つスレッドのループ反復回数は、前述のデータ構造により保持されるため、終了制御を持つスレッドが１つしか存在しない場合は、終了制御を持つスレッドに対して変数countは挿入されない。
【００８６】
ループの反復回数をカウントする変数countを用意することで、元のコード上で宣言されていたループカウンタがループ中で更新されるなどによりカウンタの数がループの反復回数と一致しないループや、元々ループカウンタが宣言されていないループ、ネストしたループなどにおいても、図１１のコード１１０１を用いて並列化を行うことができる。
【００８７】
また、並列化対象ループの持つループカウンタが単純にループの反復回数をカウントしている場合、上述の変数countを挿入せず、このループカウンタを利用してもよい。さらに、終了制御処理を持つスレッドが１つしかない場合、このスレッドでは変数countは必要ないため、図９のステップＳ１３２による処理はこのスレッドに対しては実行されない。図５のコード５０１の場合、終了制御処理が１つしかないため、終了制御処理を持つスレッドに対しては変数countを追加しない。
【００８８】
図１２は、図９のステップＳ１３３の終了処理を持つスレッドに対する処理をより詳細に示す一例のフローチャートである。先ず、ループ並列化部２０３は、ステップＳ１４０で、上述のステップＳ１３０で逐次プログラム１１０のループを分割して生成されたスレッドから、終了制御を持つスレッドを１つ選択する。終了制御を持つスレッドは、終了制御情報１２０から知ることができ、この例では、図６（ｂ）の情報６０２に従い、スレッドthread＿3が終了制御を持つスレッドとして選択される。
【００８９】
次のステップＳ１４１で、ループ並列化部２０３は、各終了制御に固有のＩＤを与える。このＩＤは、後述する終了制御の種類に関係なく、終了制御全体で固有のＩＤが与えられる。また、終了制御がある１つの処理に複数存在する場合もそれぞれ固有のＩＤが与えられる。上述の通り、終了制御が幾つ存在するのかという情報も、終了制御情報１２０から知ることができる。さらに、この例では、ＩＤは、「０」から順に付与されていくと仮定している。ＩＤの付与方法はこの例に限らず、終了制御固有のＩＤであればどんな値を付与してもよい。ただし、この例の場合のように、ＩＤをデータ構造にアクセスするための引数として直接用いている場合は、配列外のデータにアクセスするなどにより、プログラムが動作不良を起こすことがないようにＩＤを付与していく必要がある。この例では、終了制御は１つなので、その１つに対してＩＤ「０」を割り付けている。
【００９０】
次のステップＳ１４２で、ループ並列化部２０３は、逐次プログラム１１０を実行した結果と、最終的な並列化プログラム１４０を実行した結果とを一致させるための処理を実行する。このステップＳ１４２の処理は、ループの終了制御処理の特性によって異なる。終了制御処理が「break」のような最内周のループのみを終了させる処理であれば、並列化対象となるループが複数のループによってネスト（入れ子構造）した構造になっている場合に処理が必要となる。この場合、全スレッドの最内週ループが終了制御処理によって終了するまで、各スレッドは次の処理に移らず、待機状態となるようなコードを挿入する。
【００９１】
全スレッドのループが終了したら、何れか１つのスレッドに、ループ制御用の構造体をリセットするコード「reset＿cancel＿state()」を実行し、その後他のスレッドの処理を再開するようにコードを挿入する。これによってループ制御用の構造体をリセットした後、各スレッドの処理を再開することができる。また、図５のコード５０１の例のように、特に処理を行う必要がない場合は、このステップＳ１４２による処理は省略される。
【００９２】
次のステップＳ１４３で、ループ並列化部２０３は、ループ制御用のデータ構造の内容を更新する処理を、ステップＳ１４０で選択されたスレッドのコードに挿入する。より具体的には、コード１００１に対し、４１行目のコード「update＿cancel＿state(1,0)」が挿入される。挿入する場所は、ループの終了制御処理を行うか否かを判定する条件文の内部かつ終了制御処理の後以外の部分であればよい。さらに、同コード１００１における４４行目に例示されるように、コード「update＿cancel＿state(0,0)」が挿入される。挿入する場所は、あるイタレーションにおいて、ループの終了制御処理が実行されないことが確定する部分以降であり、且つ次のイタレーションの実行前の部分であればよい。
【００９３】
処理はステップＳ１４４に移行され、ループ並列化部２０３は、終了制御を持ち、選択されていないスレッドが未だ存在するか否かが判定される。若し、終了制御を持ち選択されていないスレッドが存在すると判定されたら、処理はステップＳ１４０に戻され、次の終了制御を持つスレッドが１つ選択される。一方、終了制御を持つスレッドが全て選択され上述のステップＳ１４１〜ステップＳ１４３の処理が終了していると判定されたら、この図１２のフローチャートによる一連の処理が終了される。この例の場合、図９のステップＳ１３０で分割された３つのスレッドの内、スレッドthread＿3のみが終了制御を持つため、ステップＳ１４０〜ステップＳ１４４まで一連の処理が１度ずつ実行されて、図１２のフローチャートによる処理が終了される。
【００９４】
次に、図９のステップＳ１３４による、保証する必要のあるデータを変更するスレッドに対する処理について、より詳細に説明する。図１３は、図９のステップＳ１３４の処理をより詳細に示す一例のフローチャートである。
【００９５】
先ず、ループ並列化部２０３は、ステップＳ１５０で、上述のステップＳ１３０で逐次プログラム１１０のループを分割して生成されたスレッドから、保証する必要のあるデータ、すなわち、ループ終了後に利用されるデータの値を変更するスレッドの中で、ステップＳ１５１〜ステップＳ１５３の処理を行っていないものが存在するか否かを判定する。若し、そうしたスレッドが存在すると判定されたら、処理はステップＳ１５１に移行され、ループ終了後に利用されるデータの値を変更するスレッドを１つ、選択する。
【００９６】
保証する必要のあるデータを変更するスレッド、すなわち、ループ終了後に利用されるデータの値を変更するスレッドは、変更情報１２０から知ることができる。この例では、終了制御処理を持つスレッドが１つしか存在しないため、図６（ｃ）の情報６０３に従い、スレッドthread＿2が当該スレッドとして選択される。また、図５のコード５０１のように、終了制御処理を持つスレッドが１つしか存在しない場合は、仮にこの終了制御処理を持つスレッドがループ終了後に利用されるデータの値を変更していたとしても、このスレッドに対してステップＳ１５１〜ステップＳ１５３の処理は行わないという最適化も可能である。
【００９７】
次のステップＳ１５２で、ループ並列化部２０３は、ループ終了制御処理を、ステップＳ１５１で選択されたスレッドのコードに挿入する。より具体的には、コード１００１に対して、図１０の３２行目に示されるように、ループの終了制御であるコード「break」を挿入する。
【００９８】
コード「break」が挿入される位置は、元のループ内部の処理において、スレッド内部の処理と終了制御処理の位置関係を保持した形であればどこでもよい。つまり、元のループ内部の処理において、スレッド内部の処理よりも終了制御処理の方が前に存在している場合、スレッド内部の処理の前に終了制御処理を挿入する。逆に、スレッド内部の処理よりも終了制御処理の方が後ろに存在している場合、スレッド内部の処理の後ろに終了制御処理を挿入する。
【００９９】
また、ここで挿入されるループの終了制御は、図１２の各ステップにおいて処理されたスレッドの持つ終了制御と同一のものである。この例の場合、コード「break」が使われているため、これを挿入することになる。ただし、図１２の処理ステップＳ１４４を実行した際に、ループの終了制御処理が変更されている場合は、変更された処理が挿入される。また、終了制御が複数存在する場合、この挿入処理は終了制御の個数分行われる。終了制御が複数存在する場合の各終了制御の挿入位置は、逐次プログラム１１０上での各終了制御処理の位置関係を保持した状態で挿入される。
【０１００】
次のステップＳ１５３で、ループ並列化部２０３は、ループ制御用のデータ構造を確認する処理をステップＳ１５０で選択されたスレッドのコードに挿入する。より具体的には、コード１００１に対して、図１０のコード１００１における３１行目および３３行目に示されるように、コード「if(check＿cancel＿state(count,1,0)==1)｛」および「｝」を挿入する。このコードを挿入する位置は、ステップＳ１５２で挿入されたループ終了制御処理の直前および直後とし、終了制御を囲むブロックを構成すればよい。このコード「if(check＿cancel＿state(count,1,0)==1)｛」および「｝」による処理が挿入されることで、スレッドthread＿2の処理が、スレッドthread＿3のループ処理が終了されたか継続されたかを確認し、終了した場合はスレッドthread＿2でもループ処理を終了し、継続された場合はスレッドthread＿2においてもループ処理を継続するものとなる。ステップＳ１５３での処理が終了すると、処理がステップＳ１５０に戻される。
【０１０１】
上述のステップＳ１５０で、ループ終了後に利用されるデータの値を変更するスレッドの中でステップＳ１５１からステップＳ１５３の処理を行っていないものが存在しないと判定されたら、この図１３のフローチャートによる一連の処理が終了される。この例の場合、スレッドthread＿2のみが対象となるため、ステップＳ１５０〜ステップＳ１５３の処理が１度ずつ実行されて、図１３のフローチャートによる処理が終了される。
【０１０２】
次に、図９のステップＳ１３５による、その他、すなわち、終了制御を持たず、ループ終了後に利用される値の変更も行わないスレッドに対する処理について、より詳細に説明する。図１４は、図９のステップＳ１３５の処理をより詳細に示す一例のフローチャートである。
【０１０３】
先ず、ループ並列化部２０３は、ステップＳ１６０で、終了制御情報１２０から、終了制御処理を持つスレッドが複数存在するか否かを判定する。若し、終了制御処理を持つスレッドが複数存在すると判定されたら、処理はステップＳ１６１に移行される。
【０１０４】
ステップＳ１６１で、ループ並列化部２０３は、上述のステップＳ１３０で逐次プログラム１１０のループを分割して生成されたスレッドのうち、ループ終了後に利用されるデータ、すなわち、保証する必要のあるデータを変更するスレッドの中で、選択されていないスレッド、すなわち、後述するステップＳ１６３からステップＳ１６５の処理を行っていないスレッドが存在するか否かを判定する。若し、選択されていないスレッドが存在しないと判定されたら、図１４のフローチャートによる一連の処理が終了される。一方、選択されていないスレッドが存在すると判定されたら、処理はステップＳ１６３に移行され、ループ終了後に利用されるデータの値を変更するスレッドを１つ選択する。
【０１０５】
また、上述のステップＳ１６０で、終了制御処理を持つスレッドが１つしか存在しないと判定されたら、処理はステップＳ１６２に移行される。この例の場合、終了制御処理を持つスレッドは１つなので、ステップＳ１６２に処理が移ることになる。
【０１０６】
ステップＳ１６２で、ループ並列化部２０３は、上述のステップＳ１３０で逐次プログラム１１０のループが分割されて生成されたスレッドから、上述のステップＳ１３３およびステップＳ１３４で選択されていないスレッドが存在するか否かを判定する。若し、全てのスレッドが選択されたと判定されたら、図１４のフローチャートによる一連の処理が終了される。一方、未だ選択されていないスレッドが存在すると判定されたら、処理はステップＳ１６３に移行され、未だ選択されていないスレッドが１つ選択される。この例では、スレッドthread＿1がこれまでの処理で１度も選択されていないので、このスレッドthread＿1が選択されることになる。
【０１０７】
ステップＳ１６３で、ループ並列化部２０３は、上述したように、ステップＳ１６１またはステップＳ１６２で選択対象とされたスレッドを１つ選択する。この例では、スレッドthread＿1がこれまでの処理で１度も選択されていないので、このスレッドthread＿1が選択されることになる。
【０１０８】
次のステップＳ１６４で、ループ並列化部２０３は、ループ終了制御処理を、プログラムおよびステップＳ１６３で選択されたスレッドのコードに挿入する。より具体的には、コード１００１に対して、図１０の２１行目に示されるように、ループの終了制御であるコード「break」を挿入する。
【０１０９】
コード「break」を挿入する位置は、元のループ内部の処理において、スレッド内部の処理と終了制御処理の位置関係を保持した形であればどこでもよい。つまり、元のループ内部の処理において、スレッド内部の処理よりも終了制御処理の方が前に存在している場合、スレッド内部の処理の前に終了制御処理を挿入する。逆に、スレッド内部の処理よりも終了制御処理の方が後ろに存在している場合、スレッド内部の処理の後ろに終了制御処理を挿入する。ここで挿入されるループの終了制御は図１２の各ステップにおいて処理されたスレッドの持つ終了制御と同一のものである。この例の場合、コード「break」が使われているため、これを挿入することになる。また、終了制御が複数存在する場合、この挿入処理は終了制御の個数分行われる。終了制御が複数存在する場合の各終了制御の挿入位置は、逐次プログラム１１０上での各終了制御処理の位置関係を保持した状態で挿入される。
【０１１０】
次のステップＳ１６５で、ループ並列化部２０３は、ループ制御用のデータ構造を確認する処理を、ステップＳ１６３で選択されたスレッドのコードに挿入する。より具体的にはコード１００１に対して、図１０のコード１００１における２０行目と２２行目に示されるように、コード「if(check＿cancel＿state(count,0,0)==1)｛」および「｝」を挿入する。
【０１１１】
コード「if(check＿cancel＿state(count,0,0)==1)｛」および「｝」が挿入される位置は、ステップＳ１６４で挿入されたループ終了制御処理の直前および直後とし、終了制御を囲むブロックを構成する位置に挿入すればよい。このコード「if(check＿cancel＿state(count,0,0)==1)｛」および「｝」による処理が挿入されることで、スレッドthread＿1の処理が、スレッドthread＿3のループ処理が終了されたか、継続されたかを確認し、終了した場合はスレッドthread＿1でもスレッドthread＿3でループ処理が終了した反復回数分でループ処理を終了し、継続された場合はスレッドthread＿1においてもループ処理を継続する。ステップＳ１６５での処理が終了すると、処理がステップＳ１６０に戻される。
【０１１２】
この例の場合、終了制御処理を持つスレッドが１つであり、スレッドthread＿3のみが、上述のステップＳ１３３およびステップＳ１３４で選択されていないスレッドなので、ステップＳ１６０、ステップＳ１６２〜ステップＳ１６５の処理が１度ずつ実行されて、図１４のフローチャートによる処理が終了される。それに伴い、図９のフローチャートによる一連の処理が終了され、ループ並列化部２０３による処理が終了し、中間並列化プログラム１３１の生成が完了する。この中間並列化プログラム１３１は、例えば上述のコード１１０１とコード１００１とを含む。
【０１１３】
なお、この例では、ループの終了制御にコード「break」が用いられているが、終了制御はこれに限定されるものではない。第１の例として、コード「return」のように、ループ自体を終了させると共に、そのループの所属する関数を終了させる終了制御を用いることができる。図１５（ａ）は、このようなコード「return」を終了制御として用いた逐次プログラム１１０の例を示す。この図１５（ａ）に例示されるコード１５０１は、上述した図５のコード５０１と対応するものである。コード１５０１の１０行目に、ループの終了制御としてのコード「return」が記述されている。９行目のif文が成立し、１０行目のコード「return」が実行されると、戻り値として「０」が返され、メインの関数「foo()」が終了される。
【０１１４】
図１５（ｂ）は、図１５（ａ）のコード１５０１に対して、上述した図１２、図１３および図１４のフローチャートによる処理を施した結果得られる、中間並列化プログラム１３１を構成するためのコード１５０２の例を示す。
【０１１５】
この図１５（ｂ）のコード１５０２では、先ず、図１２のステップＳ１４２にて、元のコード１５０１の終了制御コード「return」が、各スレッドにおいてそれぞれ終了制御コード「goto」に変更され、この制御コードの分岐先を意味するラベル「loop＿end」をスレッド中の並列化対象ループの終了直後に挿入する。この終了制御コードが変更されたコード１５０１に対し、さらに、コード１５０２における１３行目〜１５行目に示されるコードが挿入され、各スレッドthread＿1、thread＿2およびthread＿3が上述の操作により挿入された終了制御コード「goto」によってループが終了したか否かをチェックし、終了した場合に、コード「return」が実行されるようにする。
【０１１６】
また、この例では、並列化対象となるループが複数のループによってネストしておらず、単一のループとなっているが、これはこの例に限られず、対象ループが複数のループによってネストした構造になっていてもよい。この例の終了制御処理「return」のように、ループ自体を終了させると共に、そのループの所属する関数を終了させる終了制御を用いる場合、ラベル「loop＿end」をネストした最外周のループの終了直後に挿入することで、元の逐次プログラムと結果が異なることを回避している。
【０１１７】
また、「break」と同様に、コード「return」が複数存在してもよい。その場合、コード「return」は、それぞれ持っている戻り値が異なる可能性がある。そのため、図１２のステップＳ１４１にて割り付けられる各終了制御に固有のＩＤを用い、コード１５０２における１３行目〜１５行目に示されるコードに加え、ＩＤによる判定を追加することで、元の逐次プログラムと結果が異なることを回避できる。
【０１１８】
第２の例として、コード「goto」を利用したループ外の任意の場所の処理に飛ぶ終了制御を用いることができる。図１６（ａ）は、コード「goto」を終了制御として用いた逐次プログラム１１０の例を示す。この図１６（ａ）に例示されるコード１６０１は、上述した図５のコード５０１と対応するものである。コード１６０１の１０行目に、ループの終了制御としてのコード「goto」が記述されると共に、当該コード「goto」の飛び先として１４行目にコード「label＿1」が記述される。９行目のif文が成立し、１０行目のコード「goto」が実行されると、処理が１４行目に飛び、戻り値として「０」が返される。
【０１１９】
図１６（ｂ）は、図１６（ａ）のコード１６０１に対して、上述した図１２、図１３および図１４のフローチャートによる処理を施した結果得られる、中間並列化プログラム１３１を構成するためのコード１６０２の例を示す。
【０１２０】
この図１６（ｂ）のコード１６０２では、先ず、図１２のステップＳ１４２にて、元のコード１６０１の終了制御コード「goto」の分岐先ラベルを各スレッドにおいてそれぞれ変更し、この制御コードの分岐先を意味するラベル「loop＿end」をスレッド中の並列化対象ループの終了直後に挿入する。この終了制御コードが変更されたコード１６０１に対して、さらに、コード１６０２の１３行目に示されるコードが挿入され、各スレッドthread＿1、thread＿2およびthread＿3が上述の操作により変更された終了制御コード「goto」によってループが終了したか否かをチェックし、終了した場合に、コード「goto」が実行され、処理が１５行目のコード「label＿1」に飛ぶようにする。
【０１２１】
また、この例では、並列化対象となるループが複数のループによってネストしておらず、単一のループとなっているが、これはこの例に限られず、対象ループが複数のループによってネストした構造になっていてもよい。この例の終了制御コード「goto」のように、ループ外の任意の場所の処理に飛ぶ終了制御を用いる場合、ラベル「loop＿end」をネストした最外周のループの終了直後に挿入することで、元の逐次プログラムと結果が異なることを回避している。
【０１２２】
また、上述のコード「break」と同様に、終了制御コード「goto」が複数存在してもよい。その場合、コード「goto」はそれぞれ持っている飛び先のラベルが異なる可能性があるため、図１２のステップＳ１４１にて割り付けられる各終了制御に固有のＩＤを用い、コード１５０２における１３行目に示されるコードに加え、ＩＤによる判定を追加する。これにより、元の逐次プログラムと結果が異なることを回避できる。
【０１２３】
第３の例として、コード「continue」のように、あるイタレーションの一部分の処理だけを飛ばして、次のイタレーションの処理へ移行する終了制御を用いることができる。図１７は、コード「continue」を終了制御として用いた逐次プログラム１１０の例を示す。この図１７に例示されるコード１７０１は、上述した図５のコード５０１と対応するものである。ただし、コード５０１とは異なり、終了制御処理がループの最初に行われている。これは、コード「continue」がループの最後にある場合、仮にこのコード「continue」が無くとも処理の結果に変化がなくなってしまうためである。
【０１２４】
コード「continue」に対する処理においては、他の終了制御処理とは異なり、スレッドthread＿1のような、終了制御を含まず、且つ、ループ終了後に利用される値の変更も行わないスレッドに対しては、コードの挿入は行われない。つまり、図１４のフローチャートによる処理が実行されない。これは、コード「continue」が１回のイタレーションの処理のみを飛ばすものであるため、コード「continue」が複数回実行された際にその全てを補足し、処理を飛ばすことよりも、それらを無視して実行してしまった方がオーバーヘッドが小さくなる可能性が高いためである。図１２のフローチャートにおけるステップＳ１４３にて、図１４のフローチャートの処理を実行する処理をその対象から外すことで、上述の処理を実現できる。
【０１２５】
コード１７０１において、８行目に、ループの終了制御としてのコード「continue」が記述されている。７行目のif文が成立し、８行目のコード「continue」が実行されると、ループ内のコード「continue」以降の処理は実行されず、次のイタレーションの処理が実行される。
【０１２６】
図１８は、図１７のコード１７０１に対して、上述した図１２および図１３のフローチャートによる処理を施した結果得られる、中間並列化プログラム１３１を構成するためのコード１８０１の例を示す。
【０１２７】
また、この例では、並列化対象となるループが複数のループによってネストしておらず、単一のループとなっているが、これはこの例に限られず、対象ループが複数のループによってネストした構造になっていてもよい。また、コード「break」、「return」、「goto」および「continue」のような各終了制御処理は、並列化対象ループの内部に１種類のみが存在しているとは限らず、複数の種類の終了制御処理が存在していてもよい。
【０１２８】
以上のように、ループ並列化部２０３は、図１１のコード１１０１で定義されるデータ構造cancel＿state、関数reset＿cancel＿state()、関数update＿cancel＿state()および関数check＿cancel＿state()を用いて、逐次プログラム１１０に対する並列化処理を行ない、中間並列化プログラム１３１を生成する。なお、この段階で生成される中間並列化プログラム１３１は、スレッド間のデータ依存関係を保証するためのコードが挿入されていないため、スレッド間にデータ依存関係がある場合は正常に動作しない。この中間並列化プログラム１３１に対して、後述するプログラム変換部１０３でデータ依存関係を保証するための変換を施すことで、スレッド間にデータ依存関係がある場合でも正常に動作する並列化プログラム１４０が得られる。スレッド間にデータの依存関係が無い場合、プログラム変換部１０３は、中間並列化プログラム１３１をそのまま並列化プログラム１４０として出力する。
【０１２９】
ループ並列化部２０３で上述のようにして生成された中間並列化プログラム１３１は、出力部２０４から出力される。出力部２０４から出力される中間並列化プログラム１３１は、例えば、Ｃ言語やＪａｖａ（登録商標）言語といったプログラミング言語に従い記述される。これに限らず、Ｃ言語やＪａｖａ（登録商標）言語といったプログラム言語を、並列化用の構文を加えて拡張したプログラミング言語で記述してもよい。これに限らず、特定の処理装置に独自のプログラミング言語を用いて記述されていてもよい。さらに、プログラミング言語でなくとも、プログラム並列化部１０２とプログラム変換部１０３で中間並列化プログラム１３１に相当する情報を受け渡すことが可能ならば、プログラム並列化システム向けの中間言語や機械語などを、出力部２０４から出力してもよい。この中間並列化プログラム１３１のソースコードは、例えばテキストデータとして出力部２０４から出力される。ソースコードは、バイナリデータであってもよい。
【０１３０】
中間並列化プログラム１３１のソードコードは、１つのファイルに全ての情報を纏めて格納してもよいし、複数のファイルに情報を分割して格納してもよい。また、入力部２０１に入力される逐次プログラム１１０のソースコードと、出力部２０４から出力される中間並列化プログラム１３１のソースコードは、同一の形式で記述されていてもよいし、異なる形式で記述されていてもよい。出力部２０４による中間並列化プログラム１３１の出力は、例えば、一般的に用いられるファイルシステムを利用して行うことができる。これに限らず、中間並列化プログラム１３１のソースコードを、ネットワークを介して他の端末などに出力することもできる。さらに例えば、ＧＵＩを利用してインタラクティブに出力させることも考えられる。
【０１３１】
次に、プログラム変換部１０３の一例の機能について説明する。プログラム並列化部１０２から出力された中間並列化プログラム１３１は、プログラム変換部１０３に入力される。また、上述したように、プログラム変換部１０３に対して、プログラム解析部１０１から出力されたデータ依存情報１２２が入力される。プログラム変換部１０３は、これら中間並列化プログラム１３１とデータ依存情報１２２とに基づき、中間並列化プログラム１３１をデータの依存関係を保証した並列化プログラム１４０に変換して出力する。
【０１３２】
以下では、図１０に例示したコード１００１のプログラムを、図６（ｄ）に情報６０４として示したデータ依存情報１２２を用いて変換するものとして説明する。コード１００１をデータ依存情報１２２を反映して変換した、並列化プログラム１４０を構成するためのコード１９０１の例を、図１９に示す。なお、図１９において、コード１９０１は、このコード１９０１に関する処理が終了し本実施形態に必要な部分が完成した形態で示されている。また、並列化プログラム１４０には、コード１９０１だけでなく、図１１に示されるコード１１０１も必要となる。
【０１３３】
まず、図６（ｄ）の情報６０４における１行目の情報「thread＿1:temp[i]->thread＿2:temp[i]」により、スレッドthread＿1の変数temp[i]から、同じイタレーション回数[i]のスレッドthread＿2の変数temp[i]に対してデータ依存関係があることが分かる。これを解決するため、コード１９０１に対して、図１９におけるコード１９０１の２０行目のコード「PUT(thread＿2[i],temp[i]);」と、３１行目のコード「GET(thread＿1[i],temp[i]);」とが挿入される。
【０１３４】
ここで、２０行目のコード「PUT(thread＿2[i],temp[i]);」は、括弧「()」内の変数をメモリに一時的に保持するためのコードであり、３１行目のコード「GET(thread＿1[i],temp[i]);」は、括弧「()」内の変数をメモリから取得するためのコードである。すなわち、２０行目のコード「PUT(thread＿2[i],temp[i]);」を用いて、スレッドthread＿1から同じイタレーション回数のスレッドthread＿2に対して変数temp[i]のデータを渡し、３１行目のコードを用いて、スレッドthread＿2が同じイタレーション回数のスレッドthread＿1から、変数temp[i]のデータを受け取ることができる。
【０１３５】
この例では、ＦＩＦＯ(First  In  First  Out)を用いたデータの受け渡しを仮定している。具体的には、コードPUTによってメモリ上のＦＩＦＯの内部にデータを格納し、コードGETによってＦＩＦＯ内部のデータを取り出す形を想定している。ＦＩＦＯにおけるデータの数を増やせば、命令PUTを実行するスレッドが命令GETを行うスレッドより高速に動作する場合でも、ＦＩＦＯにデータを置ける間は、先に処理を実行することができる。ＦＩＦＯが一杯になっている場合は、ＦＩＦＯに空きがでるまでコードPUTを実行するスレッドは待機状態となる。コードGETを実行するスレッドは、ＦＩＦＯが空の場合は待機状態となる。これによって、データの依存関係を壊さずに処理を並列に実行することができる。
【０１３６】
次に、図６（ｄ）の情報６０４の２行目の情報により、スレッドthread＿2の変数totalから、スレッドthread＿3の変数totalに対してデータ依存関係があることが分かる。これを解決するため、コード１９０１に対して、さらに、図１９におけるコード１９０１の３３行目のコード「PUT(thread＿3[i],total)」と、４３行目のコード「GET(thread＿2,[i],total)」とが挿入される。このように、データ依存情報１２２に記述される全ての情報を確認し、処理を行ったら、図１９に例示されるコード１９０１と、上述したコード１１０１とを含む並列化プログラム１４０がプログラム変換部１０３から出力される。
【０１３７】
上述では、変数のスレッド間での受け渡しを、ＦＩＦＯによるコードGETおよびPUTを用いて行っているが、これはこの例に限定されない。例えば、アーキテクチャや言語固有のコードの中で、上述のコードGETおよびPUTと同様の機能を持つコードに置き換えることや、グローバル変数と一時的に特定のスレッドのみのアクセスを認めるロック機能を利用するなどによりデータ依存関係を満たすことでも、変数のスレッド間での受け渡しを実現できる。
【０１３８】
本実施形態では、ループを分割したスレッド間におけるデータ依存関係の保証を、プログラム変換部１０３により自動的に行っているが、これはこの例に限定されない。例えば、上述したような処理をユーザがテキストエディタなどを用いて直接的に行うことで、中間並列化プログラム１３１を変換して並列化プログラム１４０を生成してもよい。
【０１３９】
また、プログラム変換部１０３が出力した並列化プログラム１４０を、ユーザがテキストエディタなどを用いて直接的に改良して用いてもよい。さらに、プログラム変換部１０３が出力する並列化プログラム１４０を、データ依存関係を解決するコードの挿入部分と関係するスレッドおよびデータのみをコメントの形で挿入したものとし、ユーザがこのコメントを参照して、当該並列化プログラム１４０を、プログラムを実行する環境向けのコードに書き直すようにしてもよい。さらにまた、この場合において、データ依存関係を解決するコードの挿入部分と関係するスレッドおよびデータのみがコメントの形で挿入された並列化プログラム１４０を、実行環境向けに用意された変換装置で変換してもよい。さらに例えば、ＧＵＩを利用してインタラクティブに出力させることも考えられる。
【０１４０】
本実施形態では、プログラム解析部１０１、プログラム並列化部１０２およびプログラム変換部１０３を組み合わせて用いたが、これはこの例に限定されるものではない。例えば、プログラム解析部１０１、プログラム並列化部１０２およびプログラム変換部１０３は、本実施形態によるシステム以外の、例えば並列化コンパイラなどの他の装置向けに作成されたシステムを利用してもよいし、当該システムを本実施形態のシステム向けに改造したシステムを利用してもよい。
【０１４１】
上述したプログラム並列化システムによって出力された並列化プログラム１４０は、例えば、マルチコアのアーキテクチャ上で実行される。すなわち、マルチコアを構成するそれぞれのコアで、並列化プログラム１４０における、逐次プログラム１１０のループを分割し、並列化したスレッドのそれぞれが実行される。これに限らず、並列化プログラム１４０は、シングルコアであっても、１コア上で複数のスレッドを実行が可能なアーキテクチャであれば適用可能である。さらに、複数のＣＰＵを搭載したマルチプロセッサや、複数の計算機を用いたシステム上でも、並列に複数のスレッドの実行が可能であれば適用可能である。
【０１４２】
プログラム並列化システムから出力された並列化プログラム１４０は、コンパイラでコンパイルされ、コンピュータ上で実行される。この際、プログラム並列化部１０２で生成されたデータ構造や関数（図１１のコード１１０１参照）と、このデータ構造を操作する処理（例えば図１９のコード１９０１参照）とによって、実行前にループの反復回数が不明なループを含む逐次プログラム１１０の動作を、並列的に実行させることができる。上述の通り、図１１のコード１１０１に相当する部分は、ライブラリ等を用いた方法でも実現できるため、そのような場合は、それぞれコンピュータ上で実行可能な形式に変換される。
【０１４３】
図２０は、逐次プログラム１１０のループを、並列化した３のスレッドに分割した場合の、各スレッド間における依存関係の例を示す。図２０における処理ブロック＃１、＃２および＃３は、１回のイタレーション処理の実行に対応したスレッドを示す。また、図２０（ａ）、図２０（ｂ）および図２０（ｃ）は、それぞれ１回のイタレーション処理の実行を示す。すなわち、例えば図２０（ａ）に示される処理ブロック＃１、＃２および＃３は、対応するイタレーション回数の処理を示し、図２０（ａ）は１回目のイタレーション、図２０（ｂ）は２回目のイタレーション、図２０（ｃ）は３回目のイタレーションを示す。また、図２０の例では、各処理ブロック＃１、＃２および＃３のイタレーション１回当たりの処理時間は同じであり、同じ処理ブロック＃１〜＃３は、前のイタレーションの実行が終了するまで次のイタレーションの実行を行わないと仮定している。また、このような仮定が成り立たず、各処理ブロックの処理時間が異なったり、前のイタレーションの実行が終了しなくとも次のイタレーションの実行が行われる場合でも、上述のような依存関係の保証方法を用いることで並列化を行うことができる。
【０１４４】
さらに、図２０において、各スレッド間の矢印１０、１１および２０は、それぞれスレッド間の依存関係を表している。白抜きの矢印１０および１１は、データの依存関係を示しており、例えば、処理ブロック＃１から処理ブロック＃２へと向けた矢印１０は、処理ブロック＃１で変更されたデータが処理ブロック＃２で利用されることを示す。この場合、処理ブロック＃２の処理は、処理ブロック＃１の処理が終了するまで保留されることになる。矢印１１も同様である。
【０１４５】
このようなデータの依存関係は、既に説明したように、プログラム変換部１０３によって挿入されたコードによって保証される。上述のように、データ依存関係の設定方法は、これに限られない。
【０１４６】
図２０において、塗り潰された矢印２０は、ループの終了制御による依存関係を表す。例えば、図２０（ａ）の処理ブロック＃３から図２０（ｂ）の処理ブロック＃２へと向けた矢印２０は、処理ブロック＃３において、当該処理ブロック＃３によるループ終了後に、次のイタレーションにおいて処理ブロック＃２で利用されるデータが変更されるため、処理ブロック＃３においてループの終了制御処理によりループが終了したか否かの判定後に、次のイタレーションにおける処理ブロック＃２を実行しなければならないことを示す。この場合、例えば２回目のイタレーション（図２０（ｂ））における処理ブロック＃２は、１回目のイタレーション（図２０（ａ））における処理ブロック＃３でのループの終了または継続が確定するまで保留されることになる。
【０１４７】
このような、ループの終了制御による依存関係は、既に説明したように、終了制御情報１２０および変更情報１２１としてプログラム並列化部１０２に入力され、ループ並列化部２０３によって中間並列化プログラム１３１に挿入されるコードによって処理される。
【０１４８】
図２１は、図２０に例示した並列化されたループを実行した結果の例を示す。図２１（ａ）は、本実施形態の方法で並列化した場合の実行結果の例である。また、図２１（ｂ）は、従来技術によりロールバックを用いて並列化した場合の実行結果の例を示す。なお、図２１（ａ）および図２１（ｂ）において、縦方向の矢印は時間を示し、列Ｐ１、列Ｐ２および列Ｐ３は、それぞれ並列化された処理を実行する１つの処理装置を示し、例えばプロセッサの１つのコアを示す。また、各処理ブロック＃１、＃２および＃３は、本実施形態に対応する図２１（ａ）においては、それぞれ本実施形態において例として挙げてきたスレッドthread＿1、thread＿2およびthread＿3に対応するものとする。さらに、各処理ブロック＃１〜＃３の数字に付された添字は、イタレーションの回数を示す。例えば、処理ブロック＃１1は、スレッドthread＿1の１回目のイタレーションによる処理を示す。図２１では、各処理ブロックは決められたコアによって実行されているが、イタレーション毎に実行するコアを変更してもよい。
【０１４９】
先ず、図２１（ａ）および上述の図２０（ａ）〜図２０（ｃ）を参照し、本実施形態の方法で並列化した場合について、一例の動作を説明する。本実施形態によるプログラム並列化システムにより生成された、図１１のコード１１０１と、図１７のコード１８０１とからなる並列化プログラム１４０をそれぞれコンパイルし、リンク処理などを施して生成した実行ファイルが、例えばコンピュータのＣＰＵ上で実行されることで、各スレッドthread＿1、thread＿2およびthread＿3が実行される。
【０１５０】
図２１（ａ）において、先ず１回目のイタレーションにおけるスレッドthread＿1の処理が、ＣＰＵ上のコアの１つにより実行される。このコアは、処理ブロック＃１1すなわち１回目のイタレーションにおけるスレッドthread＿1に従い、ループ制御用のデータ構造を確認する関数check＿cancel＿state()を呼び出す。この時点ではループが終了していないので、処理が継続される。
【０１５１】
処理ブロック＃１1の１回目のイタレーションによる実行が終了すると、図１９のコード１９０１における２０行目のコードPUTによる処理と、３１行目のコードGETによる処理とによって、図２０（ａ）において矢印１０で示される、処理ブロック＃１1から処理ブロック＃２1へデータが受け渡されることで、のデータ依存関係が解決され、処理ブロック＃２1の実行が可能となる。一方、処理ブロック＃１1は、２回目のイタレーションにおける処理ブロック＃１2に対するデータの依存関係が設定されておらず、処理ブロック＃１2の実行が可能となっている。そのため、１回目のイタレーションによる処理ブロック＃２1と、２回目のイタレーションによる処理ブロック＃１2とがそれぞれ別のコアにより並列に実行される。
【０１５２】
スレッドthread＿1を実行するコアは、処理ブロック＃１2すなわち２回目のイタレーションにおけるスレッドthread＿1に従い、ループ制御用のデータ構造を確認する関数check＿cancel＿state()を呼び出す。この時点ではループが終了していないので、処理が継続される。同様に、スレッドthread＿2を実行するコアは、処理ブロック＃２1すなわち１回目のイタレーションにおけるスレッドthread＿2に従い、ループ制御用のデータ構造を確認する関数check＿cancel＿state()を呼び出す。この時点ではループが終了していないので、処理が継続される。
【０１５３】
次に、各コアにより、コード１９０１の３３行目のコードPUTによる処理と、４３行目のコードGETによる処理とが実行されることによって、図２０（ａ）において矢印１１で示される、処理ブロック＃２1から処理ブロック＃３1への依存関係が解決され、処理ブロック＃３1が実行可能となる。一方、処理ブロック＃１の次のイタレーションの処理ブロック＃１3には依存関係が設定されておらず、処理ブロック＃１3の実行が可能となっている。そのため、１回目のイタレーションによる処理ブロック＃３1と、３回目のイタレーションによる処理ブロック＃１3とがそれぞれ別のコアにより並列に実行される。
【０１５４】
スレッドthread＿1を実行するコアは、処理ブロック＃１3すなわち３回目のイタレーションにおけるスレッドthread＿1に従い、ループ制御用のデータ構造を確認する関数check＿cancel＿state()を呼び出す。この時点ではループが終了していないので、処理が継続される。
【０１５５】
一方、スレッドthread＿3を実行するコアは、処理ブロック＃３1すなわち１回目のイタレーションにおけるスレッドthread＿3に従い、ループ制御用のデータ構造を更新する関数update＿cancel＿state()を呼び出す。この時点では、ループ終了の条件を満たさなかったため、このコアは、構造体cancelのメンバ変数countを更新し、スレッドthread＿3の実行を待っている処理（この例では処理ブロック＃２2すなわち２回目のイタレーションにおけるスレッドthread＿2）に対して、１回目のイタレーションの処理が終了したことを通知し、処理を継続すると共に、図２０（ａ）において矢印２０で示される、処理ブロック＃２2の依存関係が解決される。
【０１５６】
一方、次のイタレーションの処理ブロック＃１4には依存関係が設定されていない。そのため、４回目のイタレーションによる処理ブロック＃１4と、２回目のイタレーションによる処理ブロック＃２2がそれぞれ別のコアにより実行される。
【０１５７】
スレッドthread＿1を実行するコアは、処理ブロック＃１4すなわち４回目のイタレーションにおけるスレッドthread＿1から、ループ制御用のデータ構造を確認する関数check＿cancel＿state()を呼び出す。この時点ではループが終了していないので、処理が継続される。同様に、スレッドthread＿2を実行するコアは、処理ブロック＃２2すなわち２回目のイタレーションにおけるスレッドthread＿2に従い、ループ制御用のデータ構造を確認する関数check＿cancel＿state()を呼び出す。この時点ではループが終了していないので、処理が継続される。
【０１５８】
次に、それぞれ別のコアにより、処理ブロック＃３2と、５回目のループイタレーションの処理ブロック＃１5とが実行される。スレッドthread＿3を実行するコアは、処理ブロック＃３2すなわち２回目のイタレーションにおけるスレッドthread＿3に従い、ループ制御用のデータ構造を更新する関数update＿cancel＿state()を呼び出す。この時点では、ループがスレッドthread＿1により終了され、ループ終了の条件を満たしたため、スレッドthread＿3を実行するコアは、構造体cancelのメンバ変数canceledを「１」に更新し、スレッドthread＿1およびthread＿2に対して、２回目のイタレーションの処理でループが終了したことを通知する。各コアは、次にこれらのスレッドthread＿1およびthread＿2を実行した際に、関数check＿cancel＿state()を呼び出してこの通知を確認し、ループを終了させる。
【０１５９】
次に、図２１（ｂ）に例示される、従来技術によるロールバックを用いてループを並列化した場合の処理について説明する。なお、各処理ブロック＃１’、＃２’および＃３’の依存関係は、上述の図２０に例示した依存関係と同一であるものとする。すなわち、同一イタレーションにおける処理ブロック＃１’から処理ブロック＃２’に対してデータ依存関係があり、同様に、同一イタレーションにおける処理ブロック＃２’から処理ブロック＃３’に対してデータ依存関係がある。また、処理ブロック＃３’は、次のイタレーションにおける処理ブロック＃２’に対して依存関係がある。
【０１６０】
ロールバックを用いる場合、図２０の処理ブロック＃２xで変更されるデータをメモリ上に保存した上で各処理ブロック＃１〜＃３を実行できる。そのため、図２０において矢印２０で示した、イタレーション間での依存関係を守る必要がなくなり、ループが終了した場合は、メモリに保存してあるデータを読み出すことで対応することになる。したがって、上述した図２１（ａ）で説明した本実施形態による処理と比較すると、この図２１（ｂ）に示される従来技術による処理では、処理ブロック＃２xが処理ブロック＃３ｘ-1の実行を待たずに処理を進められる。
【０１６１】
さらに、この従来技術によれば、処理ブロック＃３2’ループが終了した後に、図２１（ｂ）に処理ブロック＃２R’で示される処理により、メモリ上に保存してデータを読み出して、ループが終了した後に利用される値を保証する。データを保証するために、図２１（ｂ）において斜線を付して示される処理ブロック＃２1’、＃２2’および＃２3’のデータがメモリ上に保存されている必要がある。処理ブロック＃２R’は、このメモリ上に保存されているデータの中から、ループ終了が発生した２回目のイタレーションにおける処理ブロック＃２2’のデータを呼び出す必要がある。これに対し、本実施形態では、並列化を行うための余分なメモリ領域を確保せずに、実行前にループの反復回数が不明なループを含むプログラムを並列化できる。したがって、本実施形態は、図２１（ｂ）に例示した従来技術による方法と比べて、必要なメモリ領域を削減することができる。
【０１６２】
ロールバックを用いる場合、上述のように、余分なメモリ領域を必要とすると共に、メモリへのデータの保存および読み出しが必要となるため、オーバーヘッドが発生し、本実施形態と比較した場合、処理時間が余計にかかってしまう可能性がある。図２１（ｂ）の例ではイタレーション毎にデータの保存を行う必要があり、本実施形態に比べてオーバーヘッドが大きくなってしまう。
【０１６３】
そこで、比較例（特開平１１−１２０００３号公報）に示されるように、所定回数毎、例えば１０回分のイタレーションが実行される毎に、データ保存を行うことで、保存するデータ量を軽減する方法が提案されている。また、比較例において、データ保存の際、過去２回分のみのデータを保存することによって、保存するデータ量をさらに削減することができる。この場合、データを保存する時点で、例えば１０回前と２０回前のデータを保存してあることになる。
【０１６４】
図２１（ｂ）を用いて説明すると、処理ブロック＃１1は、処理ブロック＃１の１回目〜１０回目までの実行を示すことになる。他のブロックも同様となるため、図２１（ｂ）の例では、処理ブロック＃３1でループの終了が検出されることになる。この後、ループ実行前の初期状態のデータをメモリから読み出した後に、処理ブロック＃１、＃２および＃３の１回目のループの結果と２回目のループの結果とを再計算することになる。本実施形態の場合、予め計算した部分が完全に無駄になってしまうため、所定回数毎にデータ保存を行うようにしたロールバックを用いる方法に比べて、オーバーヘッドが大きくなるおそれがある。
【０１６５】
このように、比較例に示される従来技術では、ロールバックにおいてメモリが圧迫されるという問題は、軽減されている。しかしながら、データを保存するという操作は必要であるため、過去２回分のデータに関してはデータ保存用のメモリ領域が必要となる。このため、並列化前の逐次プログラムの時点ですでにメモリ領域にそれほど余裕がない場合は適用できない可能性がある。
【０１６６】
本実施形態によれば、比較例に対し、メモリ領域の削減と共に、並列化プログラムの制御を簡略化できる。図２２は、比較例による並列化プログラムの制御方法を概略的に示す一例のフローチャートである。比較例によりループが並列化された並列化プログラムを実行する場合、スレッドを実行する各コアは、実行対象の処理ブロックが実行可能となるまで待機し（ステップＳ２００）、当該処理ブロックが実行されると、当該処理ブロックにおける終了処理により、ループからの飛び出し処理が発生したか否かを判定する（ステップＳ２０１）。若し、終了制御による終了処理が発生したと判定したら、各コアは、プログラムの実行中に処理ブロックによりメモリに保存されたたデータをロードして（ステップＳ２０４）、ロードしたデータを用いて再計算を行い（ステップＳ２０５）、ループを終了させる。
【０１６７】
各コアは、ステップＳ２０１でループの終了処理が発生していないと判定したら、処理をステップＳ２０２に移行させ、ループが規定の回数に達したか否かを判定する。若し、規定の回数に達していないと判定したら、各コアは、処理をステップＳ２００に戻し、例えば次の処理ブロックの処理を実行する。一方、ループが規定の回数に達したと判定したら、各コアは、処理をステップＳ２０３に移行させて、実行中の処理ブロックで出力されるデータをメモリに保存し、処理をステップＳ２００に戻す。
【０１６８】
この図２２のフローチャートによる処理において、斜線を付して示したステップＳ２０２、ステップＳ２０３、ステップＳ２０４およびステップＳ２０５の処理は、比較例に特有の処理であって、本実施形態では不要な処理である。したがって、本実施形態では、比較例の処理に対して、ループが規定回数に達したかどうかの判定、必要なデータの保存、保存したデータのロード、ロードしたデータによる再計算といった処理が削減され、全体として処理が簡略化されている。
【０１６９】
特に、必要なデータの保存、保存されたデータのロードは、比較例において、比較的負荷の大きな処理である。すなわち、比較例では、必要なデータ全てをメモリ領域の別の場所に保存しておく必要があるため、データの大きさやアーキテクチャによってはデータの保存に長時間を要する場合がある。また、データのロードの際にも、保存されているデータの中から正しいデータを読み出し、適切なデータに上書きすることが必要になるため、データの保存に対して長時間を要する。本実施形態では、これらの比較的負荷の大きな処理が省略されているため、並列化によるプログラムの実行速度の向上の観点から、比較例に対して有利である。
【０１７０】
さらに、比較例では、必要なデータがどれなのか、それがどの程度のデータ量なのかを解析することで、必要なメモリ領域を確保し、プログラムの並列化を実現している。しかしながら、必要なデータの中にポインタを介したメモリアクセスを行うデータが含まれているなどの場合は、このような解析を行うことが難しく、並列化を実現することが困難になる。本実施形態によれば、ロールバックのためのデータ保存を行わないため、ループ終了後に利用されるデータの値を変更するか否かだけをスレッド毎に判定すればよい。それと共に、必要なデータの保存を行わないために、データ量の解析は不要となり、データ解析処理を簡略化することができる。これにより、比較例に対して、並列化を実行できるループの種類が多くなる。
【０１７１】
次に、本実施形態によるプログラム並列化システムを実現可能な構成について、図２３を用いて説明する。図２３に例示されるように、本実施形態によるプログラム並列化システムは、例えば一般的なコンピュータにより実現可能である。
【０１７２】
図２３において、バス３００に対してＣＰＵ３１０、ＲＡＭ(Random  Access  Memory)３１１、ＲＯＭ(Read  Only  Memory)３１２、表示制御部３１３および通信Ｉ／Ｆ（インターフェイス）３１４が接続される。また、バス３００に対して、ハードディスクドライブ（ＨＤＤ）３１５、ドライブ装置３１６および入力Ｉ／Ｆ３１７が接続される。
【０１７３】
ＣＰＵ３１０は、ＲＯＭ３１２やＨＤＤ３１５に記憶されるプログラムに従い、ＲＡＭ３１１をワークメモリとして用いて、このコンピュータの全体を制御する。表示制御部３１３は、ＣＰＵ３１０により生成された表示制御信号を、表示装置３２０が表示可能な信号に変換して出力する。
【０１７４】
ＨＤＤ３１５は、上述のＣＰＵ３１０が実行するためのプログラムや、プログラムによって用いられるデータなどが格納される。ドライブ装置３１６は、脱着可能な記録媒体３２１が装填可能とされ、当該記録媒体３２１に対するデータの読み書きを行うことができる。ドライブ装置３１６が対応可能な記録媒体３２１としては、ＣＤ(Compact  Disk)、ＤＶＤ(Digital  Versatile  Disk)、フレキシブルディスクといったディスク記録媒体や、読み書き可能で不揮発性の半導体メモリが考えられる。
【０１７５】
入力Ｉ／Ｆ３１７は、外部からのデータの入力を行う。例えば、入力Ｉ／Ｆ３１７は、ＵＳＢ(Universal  Serial  Bus)やＩＥＥＥ１３９４(Institute  of  Electrical  and  Electronics  Engineers  1394)といった所定のインターフェイスを有し、このインターフェイスにより外部の機器からのデータ入力を行う。また、入力Ｉ／Ｆ３１７に対して、キーボード３２２やマウス３２３といった入力デバイスが接続される。ユーザは、例えば表示装置３２０に対する表示に応じてこれら入力デバイスを操作することで、このコンピュータに対して指示を出すことができる。
【０１７６】
通信Ｉ／Ｆ３１４は、所定のプロトコルを用いて外部の通信ネットワークと通信を行う。
【０１７７】
上述したプログラム並列化システムにおけるプログラム解析部１０１、プログラム並列化部１０２およびプログラム変換部１０３は、ＣＰＵ３１０上で動作するプログラムによって実現される。逐次プログラム１１０やループ分割情報１３０は、例えば他のコンピュータで作成され記録媒体３２１に記録されてこのコンピュータに供給される。これに限らず、逐次プログラム１１０やループ分割情報１３０は、外部からネットワークを介してこのコンピュータに供給するようにしてもよいし、キーボード３２２から入力してもよい。このコンピュータに供給された逐次プログラム１１０やループ分割情報１３０は、例えばＨＤＤ３１５やＲＡＭ３１１に記憶される。
【０１７８】
本実施形態に係るプログラム並列化システムを実行するためのプログラムは、インストール可能な形式又は実行可能な形式のファイルでＣＤ−ＲＯＭ、フレキシブルディスク、ＤＶＤなどのコンピュータで読み取り可能な記録媒体に記録して提供される。これに限らず、プログラム並列化システムを実行するためのプログラムを、ＲＯＭ３１２に予め記憶させて提供してもよい。
【０１７９】
さらに、本実施形態に係るプログラム並列化システムを実行するためのプログラムを、インターネットなどのネットワークに接続されたコンピュータ上に格納し、ネットワーク経由でダウンロードさせることにより提供するように構成してもよい。また、本実施形態に係るプログラム並列化システムを実行するためのプログラムを、インターネットなどのネットワーク経由で提供または配布するように構成してもよい。
【０１８０】
本実施形態に係るプログラム並列化システムを実行するためのプログラムは、上述した各部（プログラム解析部１０１、プログラム並列化部１０２およびプログラム変換部１０３）を含むモジュール構成となっており、実際のハードウェアとしては、ＣＰＵ３１０が例えばＨＤＤ３１５から当該プログラムを読み出して実行することにより上述の各部がＲＡＭ３１１上にロードされ、各部がＲＡＭ３１１上に生成されるようになっている。
【０１８１】
一例として、ＣＰＵ３１０は、プログラム解析部１０１により、ＨＤＤ３１５やＲＡＭ３１１から読み出した逐次プログラム１１０およびループ分割情報１３０に基づき逐次プログラム１１０を解析し、終了制御情報１２０、変更情報１２１およびデータ依存情報１２２を出力する。これら終了制御情報１２０、変更情報１２１およびデータ依存情報１２２は、ＨＤＤ３１５やＲＡＭ３１１を介してプログラム並列化部１０２に渡される。ＣＰＵ３１０は、プログラム並列化部１０２により、これら終了制御情報１２０および変更情報１２１と、ＨＤＤ３１５やＲＡＭ３１１から読み出した逐次プログラム１１０およびループ分割情報１３０とに基づき中間並列化プログラム１３１を出力する。この中間並列化プログラム１３１は、ＨＤＤ３１５やＲＡＭ３１１を介してプログラム変換部１０３に渡される。ＣＰＵ３１０は、プログラム変換部１０３により、この中間並列化プログラム１３１と、ＨＤＤ３１５やＲＡＭ３１１から読み出したデータ依存情報１２２に基づき並列化プログラム１４０を生成する。生成された並列化プログラム１４０は、例えばドライブ装置３１６により記録媒体３２１に記録されたり、通信Ｉ／Ｆ３１４からネットワークに向けて送信されるなどして、外部に出力される。
【０１８２】
なお、上述では、プログラム解析部１０１、プログラム並列化部１０２およびプログラム変換部１０３が１つのコンピュータ上で動作するように説明したが、これはこの例に限られない。例えば、プログラム解析部１０１、プログラム並列化部１０２およびプログラム変換部１０３のうち１または複数がそれぞれ異なるコンピュータ上で動作するようにしてもよい。この場合、終了制御情報１２０、変更情報１２１およびデータ依存情報１２２は、記録媒体３２１やネットワークを介してプログラム並列化部１０２やプログラム変換部１０３に供給される。同様に、中間並列化プログラム１３１は、記録媒体３２１やネットワークを介してプログラム変換部１０３に供給される。
【０１８３】
なお、本実施形態は、上述したそのままに限定されるものではなく、実施段階ではその要旨を逸脱しない範囲で構成要素を変形して具体化できる。また、上述の実施形態に開示されている複数の構成要素の適宜な組み合わせにより、種々の発明を形成できる。例えば、実施形態に示される全構成要素から幾つかの構成要素を削除してもよい。さらに、異なる実施形態にわたる構成要素を適宜組み合わせてもよい。
【符号の説明】
【０１８４】
１０１  プログラム解析部
１０２  プログラム並列化部
１０３  プログラム変換部
１１０  逐次プログラム
１２０  終了制御情報
１２１  変更情報
１２２  データ依存情報
１３０  ループ分割情報
１３１  中間並列化プログラム
１４０  並列化プログラム
２０１  入力部
２０２  ループ変換部
２０３  ループ並列化部
２０４  出力部
【図１】
0005148674.tif 000002
【図２】
0005148674.tif 000003
【図３】
0005148674.tif 000004
【図４】
0005148674.tif 000005
【図５】
0005148674.tif 000006
【図６】
0005148674.tif 000007
【図７】
0005148674.tif 000008
【図８】
0005148674.tif 000009
【図９】
0005148674.tif 000010
【図１０】
0005148674.tif 000011
【図１１】
0005148674.tif 000012
【図１２】
0005148674.tif 000013
【図１３】
0005148674.tif 000014
【図１４】
0005148674.tif 000015
【図１５】
0005148674.tif 000016
【図１６】
0005148674.tif 000017
【図１７】
0005148674.tif 000018
【図１８】
0005148674.tif 000019
【図１９】
0005148674.tif 000020
【図２０】
0005148674.tif 000021
【図２１】
0005148674.tif 000022
【図２２】
0005148674.tif 000023
【図２３】
0005148674.tif 000024