(57)【特許請求の範囲】
【請求項１】
複数のタスクの定義を含む第１のソースプログラムと何れかのタスクで呼び出される複数の関数の定義を含む第２のソースプログラムとを記憶する記憶部と、
前記第１および前記第２のソースプログラムのコンパイルの際に、前記第１のソースプログラムにおけるタスクの定義に応じた命令の実行に要する第１のサイクル数を示す情報と当該タスクで呼び出される関数を示す呼び出し関係情報とをタスク毎に生成し、前記第２のソースプログラムに含まれる関数の実行に要する第２のサイクル数を示す情報を関数毎に生成し、
リンク処理の際に、前記呼び出し関係情報に基づく前記タスクで呼び出される関数の特定、および、前記タスクに対応する前記第１のサイクル数と特定した当該関数に対応する前記第２のサイクル数とに基づく前記タスクの実行に要するサイクル数の算出を、タスク毎に実行する演算部、
を有するコンパイルを行う計算機。
【請求項２】
前記演算部は、前記第１のソースプログラムのコンパイル時に生成された前記第１のサイクル数を示す情報および前記呼び出し関係情報を前記第１のソースプログラムのコンパイルにより生成された第１のオブジェクトファイルに追加し、前記第２のソースプログラムのコンパイル時に生成された前記第２のサイクル数を示す情報を、前記第２のソースプログラムのコンパイルにより生成された第２のオブジェクトファイルに追加する、請求項１記載の計算機。
【請求項３】
前記演算部は、前記リンク処理の際に、結合対象の前記第１のオブジェクトファイルから前記第１のサイクル数および前記呼び出し関係情報を取得し、結合対象の前記第２のオブジェクトファイルから前記第２のサイクル数を取得する、請求項２記載の計算機。
【請求項４】
前記演算部は、前記リンク処理の際に、並列に実行可能な複数のタスクそれぞれのサイクル数に基づいて、前記複数のタスクそれぞれに割り当てるスレッド数を決定する、請求項１乃至３の何れか１項に記載の計算機。
【請求項５】
前記演算部は、前記複数のタスクそれぞれに割り当てるスレッド数の組み合わせの候補毎に前記複数のタスクそれぞれのサイクル数を算出し、前記複数のタスクそれぞれのサイクル数の差が最小になるスレッド数の組み合わせを選択する、請求項４記載の計算機。
【請求項６】
前記演算部は、決定したスレッド数の情報を前記第１のソースプログラムのコンパイルにより生成された第１のオブジェクトファイルに追加し、前記第１のオブジェクトファイルを用いて実行可能ファイルを生成する、請求項４または５記載の計算機。
【請求項７】
コンピュータに、
複数のタスクの定義を含む第１のソースプログラムのコンパイルの際に、前記第１のソースプログラムにおけるタスクの定義に応じた命令の実行に要する第１のサイクル数を示す情報と当該タスクで呼び出される関数を示す呼び出し関係情報とをタスク毎に出力し、
何れかのタスクで呼び出される複数の関数の定義を含む第２のソースプログラムのコンパイルの際に、前記第２のソースプログラムに含まれる関数の実行に要する第２のサイクル数を示す情報を関数毎に出力する、
処理を実行させるコンパイラプログラム。
【請求項８】
コンピュータに、
複数のタスクの定義を含む第１のソースプログラムのコンパイルの際に生成された、前記第１のソースプログラムにおけるタスクの定義に応じた命令の実行に要する第１のサイクル数を示す情報と当該タスクで呼び出される関数を示す呼び出し関係情報とをタスク毎に取得し、
何れかのタスクで呼び出される複数の関数の定義を含む第２のソースプログラムのコンパイルの際に生成された、前記第２のソースプログラムに含まれる関数の実行に要する第２のサイクル数を示す情報を関数毎に取得し、
前記呼び出し関係情報に基づく前記タスクで呼び出される関数の特定、および、前記タスクに対応する前記第１のサイクル数と特定した当該関数に対応する前記第２のサイクル数とに基づく前記タスクの実行に要するサイクル数の算出をタスク毎に実行する、
処理を実行させるリンクプログラム。
【請求項９】
コンピュータが、
複数のタスクの定義を含む第１のソースプログラムのコンパイルの際に、前記第１のソースプログラムにおけるタスクの定義に応じた命令の実行に要する第１のサイクル数を示す情報と当該タスクで呼び出される関数を示す呼び出し関係情報とをタスク毎に生成し、
何れかのタスクで呼び出される複数の関数の定義を含む第２のソースプログラムのコンパイルの際に、前記第２のソースプログラムに含まれる関数の実行に要する第２のサイクル数を示す情報を関数毎に生成し、
リンク処理の際に、前記呼び出し関係情報に基づく前記タスクで呼び出される関数の特定、および、前記タスクに対応する前記第１のサイクル数と特定した当該関数に対応する前記第２のサイクル数とに基づく前記タスクの実行に要するサイクル数の算出をタスク毎に実行する、
コンパイル方法。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は計算機、コンパイラプログラム、リンクプログラムおよびコンパイル方法に関する。
【背景技術】
【０００２】
コンピュータソフトウェアを開発する場合、開発者はプログラミング言語としてＣ言語などの高級言語を使用することが多い。高級言語で記述されたソースコードは、コンパイラによりプロセッサが実行可能なオブジェクトコードに変換できる。また、リンカによって、オブジェクトコードを含むオブジェクトファイルと当該オブジェクトコードから参照される他のオブジェクトファイルやライブラリとを結合し、実行ファイルを生成できる。
【０００３】
ところで、プログラムに記述された幾つかの処理を並列に実行することで、処理を高速化することがある。例えば、実行分のループの制御構造とデータの依存関係に基づいて、並列実行可能と判定されるループ内の条件式を認識し、並列実行用タスクを生成する前に条件式が成立する条件を求め、当該ループをその実行条件化で並列実行するループに変形する提案がある。また、各並列処理タスクの単位時間当たりの処理データ量と単位時間当たりの入力データ量とを基に、各並列処理タスクの実行終了時間が均等になるようにプロセッサ数を各並列処理タスクに割り当てる提案もある。
【０００４】
更に、タスク全体の高速化を実現するために、タスクの実行順番や開始時間を制御するスケジューリングコードをオブジェクトコードに挿入する提案もある。
【先行技術文献】
【特許文献】
【０００５】
【特許文献１】特開平６−２５０９８８号公報
【特許文献２】特開平６−１８７３０９号公報
【特許文献３】国際公開第２００８／０７２３３４号
【発明の概要】
【発明が解決しようとする課題】
【０００６】
複数のタスクを並列に実行する場合、各タスクの実行に要するクロックサイクル数（単にサイクル数ということがある）を把握することが考えられる。例えば、サイクル数に応じて各タスクに対する処理能力（例えば、スレッド数）の割り当てを行い得る。ところが、タスクやタスクから呼び出される関数の定義が別個のソースファイルに記述されていることがある。この場合、コンパイルはソースファイル毎に行われるため、関数のサイクル数も含めた各タスクのサイクル数をコンパイラで判断することが難しい。
【０００７】
１つの側面では、本発明は、各タスクのサイクル数を適切に取得できる計算機、コンパイラプログラム、リンクプログラムおよびコンパイル方法を提供することを目的とする。
【課題を解決するための手段】
【０００８】
１つの態様では、コンパイルを行う計算機が提供される。この計算機は、記憶部と演算部とを有する。記憶部は、複数のタスクの定義を含む第１のソースプログラムと何れかのタスクで呼び出される複数の関数の定義を含む第２のソースプログラムとを記憶する。演算部は、第１および第２のソースプログラムのコンパイルの際に、第１のソースプログラムにおけるタスクの定義に応じた命令の実行に要する第１のサイクル数を示す情報と当該タスクで呼び出される関数を示す呼び出し関係情報とをタスク毎に生成し、第２のソースプログラムに含まれる関数の実行に要する第２のサイクル数を示す情報を関数毎に生成し、リンク処理の際に、呼び出し関係情報に基づくタスクで呼び出される関数の特定、および、タスクに対応する第１のサイクル数と特定した当該関数に対応する第２のサイクル数とに基づくタスクの実行に要するサイクル数の算出を、タスク毎に実行する。
【０００９】
また、１つの態様では、コンパイラプログラムが提供される。このコンパイラプログラムは、コンピュータに、複数のタスクの定義を含む第１のソースプログラムのコンパイルの際に、第１のソースプログラムにおけるタスクの定義に応じた命令の実行に要する第１のサイクル数を示す情報と当該タスクで呼び出される関数を示す呼び出し関係情報とをタスク毎に出力し、何れかのタスクで呼び出される複数の関数の定義を含む第２のソースプログラムのコンパイルの際に、第２のソースプログラムに含まれる関数の実行に要する第２のサイクル数を示す情報を関数毎に出力する、処理を実行させる。
【００１０】
また、１つの態様では、リンクプログラムが提供される。このリンクプログラムは、コンピュータに、複数のタスクの定義を含む第１のソースプログラムのコンパイルの際に生成された、第１のソースプログラムにおけるタスクの定義に応じた命令の実行に要する第１のサイクル数を示す情報と当該タスクで呼び出される関数を示す呼び出し関係情報とをタスク毎に取得し、何れかのタスクで呼び出される複数の関数の定義を含む第２のソースプログラムのコンパイルの際に生成された、第２のソースプログラムに含まれる関数の実行に要する第２のサイクル数を示す情報を関数毎に取得し、呼び出し関係情報に基づくタスクで呼び出される関数の特定、および、タスクに対応する第１のサイクル数と特定した当該関数に対応する第２のサイクル数とに基づくタスクの実行に要するサイクル数の算出をタスク毎に実行する、処理を実行させる。
【００１１】
また、１つの態様では、コンパイル方法が提供される。このコンパイル方法では、コンピュータが、複数のタスクの定義を含む第１のソースプログラムのコンパイルの際に、第１のソースプログラムにおけるタスクの定義に応じた命令の実行に要する第１のサイクル数を示す情報と当該タスクで呼び出される関数を示す呼び出し関係情報とをタスク毎に生成し、何れかのタスクで呼び出される複数の関数の定義を含む第２のソースプログラムのコンパイルの際に、第２のソースプログラムに含まれる関数の実行に要する第２のサイクル数を示す情報を関数毎に生成し、リンク処理の際に、呼び出し関係情報に基づくタスクで呼び出される関数の特定、および、タスクに対応する第１のサイクル数と特定した当該関数に対応する第２のサイクル数とに基づくタスクの実行に要するサイクル数の算出をタスク毎に実行する。
【発明の効果】
【００１２】
１つの側面では、各タスクのサイクル数を適切に取得できる。
【図面の簡単な説明】
【００１３】
【図１】第１の実施の形態の計算機を示す図である。
【図２】第１のソースプログラムの例を示す図である。
【図３】第２のソースプログラムの例を示す図である。
【図４】第２の実施の形態の情報処理装置のハードウェア例を示す図である。
【図５】情報処理装置のソフトウェア例を示す図である。
【図６】ファイルの例を示す図である。
【図７】ソースプログラムの例（その１）を示す図である。
【図８】ソースプログラムの例（その２）を示す図である。
【図９】関数に対する命令列の例を示す図である。
【図１０】サイクル数テーブルの例を示す図である。
【図１１】タスク範囲情報の例を示す図である。
【図１２】関数コスト情報の例を示す図である。
【図１３】関数呼び出し情報の例を示す図である。
【図１４】オブジェクトファイルの例（その１）を示す図である。
【図１５】オブジェクトファイルの例（その２）を示す図である。
【図１６】タスクおよび関数の呼び出し関係の例を示す図である。
【図１７】タスクコストテーブルの例を示す図である。
【図１８】スレッド数の決定例を示す図である。
【図１９】スレッド数の設定例を示す図である。
【図２０】コンパイル処理の例を示すフローチャートである。
【図２１】リンク処理の例を示すフローチャートである。
【図２２】スレッド数決定処理の例を示すフローチャートである。
【図２３】ソースプログラムの他の例を示す図である。
【図２４】タスクと関数との入れ子構造の例を示す図である。
【発明を実施するための形態】
【００１４】
以下、本実施の形態を図面を参照して説明する。
［第１の実施の形態］
図１は、第１の実施の形態の計算機を示す図である。
【００１５】
計算機１は、ソースプログラム（ソースコードということもある）をコンパイルしてオブジェクトコードを生成する。例えば、計算機１は、第１のソースプログラム４をコンパイルして第１のオブジェクトファイル４ａを生成する。第１のオブジェクトファイル４ａは、第１のソースプログラム４に対するオブジェクトコードを含む。また、計算機１は、第２のソースプログラム５をコンパイルして第２のオブジェクトファイル５ａを生成する。第２のオブジェクトファイル５ａは、第２のソースプログラム５に対するオブジェクトコードを含む。第２のソースプログラム５は、第１のソースプログラム４とは異なるソースプログラムファイル（ソースファイルということもある）に含まれる。計算機１は、「コンピュータ」と呼ばれてもよい。
【００１６】
計算機１は、記憶部１ａおよび演算部１ｂを有する。記憶部１ａは、ＲＡＭ（Random Access Memory）などの揮発性の記憶装置でもよいし、ＨＤＤ（Hard Disk Drive）などの不揮発性の記憶装置でもよい。演算部１ｂは、例えば、プロセッサである。プロセッサは、ＣＰＵ（Central Processing Unit）やＤＳＰ（Digital Signal Processor）であってもよく、ＡＳＩＣ（Application Specific Integrated Circuit）やＦＰＧＡ（Field Programmable Gate Array）などの集積回路を含んでもよい。プロセッサは、例えば、ＲＡＭに記憶されたプログラムを実行する。後述するコンパイル処理を実現するプログラムをコンパイラプログラムと呼んでもよい。また、後述するリンク処理を実現するプログラムをリンクプログラムと呼んでもよい。また、「プロセッサ」は、２以上のプロセッサの集合（マルチプロセッサ）であってもよい。
【００１７】
記憶部１ａは、ソースプログラムを記憶する。ソースプログラムは、ユーザから計算機１に入力されたものでもよいし、計算機１がネットワークを介して他の計算機から受信したものでもよい。
【００１８】
演算部１ｂは、コンパイル処理を実行する。具体的には、演算部１ｂは、ソースプログラムを記憶部１ａから取得し、コンパイルすることで、オブジェクトファイルを生成する。オブジェクトファイルは、ソースプログラムに応じたオブジェクトコードを含む。演算部１ｂは、生成したオブジェクトファイルを、記憶部１ａに格納してもよいし、ネットワークを介して他の計算機や外部記憶装置に格納してもよい。演算部１ｂは、ソースファイル毎にコンパイルを行う。例えば、演算部１ｂは、コンパイラプログラムを実行することで、コンパイル処理を実行するコンパイラ２の機能を発揮し得る。
【００１９】
演算部１ｂは、リンク処理を実行する。具体的には、演算部１ｂは、生成したオブジェクトファイルと、当該オブジェクトコードから参照される他のオブジェクトファイルやライブラリとを結合し、実行ファイルを生成する。例えば、演算部１ｂは、リンクプログラムを実行することで、リンク処理を実行するリンカ３の機能を発揮し得る。
【００２０】
演算部１ｂは、ソースプログラムのコンパイルの際に、ソースプログラムに含まれる関数毎の実行に要するクロックサイクル数（単にサイクル数ということがある）とタスクおよび関数の呼び出し関係とを示す情報を生成する。関数は、ルーチン（メインルーチンがサブルーチンを呼び出すという呼び出し関係があり得る）と呼ばれるものでもよい。
【００２１】
例えば、演算部１ｂが第１のソースプログラム４をコンパイルする場合を考える。第１のソースプログラム４は、並列に実行可能なタスク（並列タスクと称することがある）であるタスクαおよびタスクβの定義を含む。例えば、演算部１ｂは、第１のソースプログラム４に含まれる定型の構文を特定することで、並列タスクα，βを特定し得る。例えば、タスクαは、関数ｆｕｎｃ１の呼び出しを行うコード“ｃａｌｌ  ｆｕｎｃ１”を含む。例えば、タスクβは、関数ｆｕｎｃ２の呼び出しを行うコード“ｃａｌｌ  ｆｕｎｃ２”を含む。関数ｆｕｎｃ１，ｆｕｎｃ２の定義は、第２のソースプログラム５に記述されている。
【００２２】
演算部１ｂは、タスクα，βそれぞれの定義箇所に含まれる命令の実行に要するサイクル数を取得する。例えば、記憶部１ａは、オブジェクトコードにおける各命令の実行に要するサイクル数の情報を予め記憶してもよい。すると、演算部１ｂは、当該情報に基づいて、タスクαの直下に存在するタスク内命令のサイクル数の合計を求めることができる（ループが含まれる場合は、ループの回転数も考慮される）。ただし、関数ｆｕｎｃ１の定義は第２のソースプログラム５に存在するため、関数ｆｕｎｃ１のサイクル数をも合算したサイクル数を求められるわけではない。また、演算部１ｂは、タスクβの直下に存在するタスク内命令のサイクル数の合計を求めることができる。ただし、関数ｆｕｎｃ２の定義は第２のソースプログラム５に存在するため、関数ｆｕｎｃ２のサイクル数をも合算したサイクル数を求められるわけではない。
【００２３】
また、例えば、演算部１ｂは、タスクα，βおよび関数ｆｕｎｃ１，ｆｕｎｃ２の呼び出し関係を特定する。前述のように、タスクαには、関数ｆｕｎｃ１を呼び出すコードが含まれる。よって、演算部１ｂは、タスクαが関数ｆｕｎｃ１を呼び出すという呼び出し関係を得る。また、タスクβには、関数ｆｕｎｃ２を呼び出すコードが含まれる。よって、演算部１ｂは、タスクβが関数ｆｕｎｃ２を呼び出すという呼び出し関係を得る。演算部１ｂは、タスクα，β内の命令のサイクル数およびタスクα，βと関数ｆｕｎｃ１，ｆｕｎｃ２との呼び出し関係の情報を第１のオブジェクトファイル４ａに含めてもよい。
【００２４】
次に、演算部１ｂが第２のソースプログラム５をコンパイルする場合を考える。第２のソースプログラム５は、関数ｆｕｎｃ１，ｆｕｎｃ２の定義を含む。例えば、演算部１ｂは、第２のソースプログラム５に含まれる定型の構文を特定することで、関数ｆｕｎｃ１，ｆｕｎｃ２の定義箇所を特定し得る。演算部１ｂは、関数ｆｕｎｃ１の定義箇所に含まれる命令の実行に要するサイクル数を取得する。演算部１ｂは、関数ｆｕｎｃ２の定義箇所に含まれる命令の実行に要するサイクル数を算出する。前述のように、演算部１ｂは、オブジェクトコードの各命令の実行に要するサイクル数の情報を基に、関数ｆｕｎｃ１，ｆｕｎｃ２のサイクル数を算出してもよい。関数ｆｕｎｃ１，ｆｕｎｃ２それぞれは、他の関数を呼び出すコードを含まないので、演算部１ｂは、呼び出し関係として、関数ｆｕｎｃ１，ｆｕｎｃ２それぞれからの他の関数の呼び出しはないという情報を得る。ただし、関数ｆｕｎｃ１，ｆｕｎｃ２それぞれから他の関数を更に呼び出すこともある。演算部１ｂは、関数ｆｕｎｃ１，ｆｕｎｃ２について取得したサイクル数および呼び出し関係の情報を第２のオブジェクトファイル５ａに含めてもよい。
【００２５】
第１のソースプログラム４および第２のソースプログラム５に対する上記のコンパイル処理は、演算部１ｂにより実現されるコンパイラ２によって実行されてもよい。
演算部１ｂは、リンク処理の際に、コンパイル時に生成したサイクル数および呼び出し関係の情報に基づいて、タスク毎の実行に要するサイクル数を算出する。例えば、演算部１ｂが第１のオブジェクトファイル４ａと第２のオブジェクトファイル５ａとを結合して実行可能ファイルを生成する場合を考える。
【００２６】
例えば、演算部１ｂは、タスクα内命令のサイクル数を第１のオブジェクトファイル４ａから取得する。また、演算部１ｂは、タスクαから関数ｆｕｎｃ１を呼び出すという呼び出し関係を第１のオブジェクトファイル４ａから取得する。すると、例えば、演算部１ｂは、関数ｆｕｎｃ１のサイクル数を第２のオブジェクトファイル５ａから取得する。演算部１ｂは、タスクαおよび関数ｆｕｎｃ１について第１のオブジェクトファイル４ａおよび第２のオブジェクトファイル５ａから取得したサイクル数の合計をタスクαの実行に要するサイクル数（タスクα全体のサイクル数といってもよい）とする。
【００２７】
同様に、例えば演算部１ｂは、タスクβ内の命令のサイクル数を第１のオブジェクトファイル４ａから取得する。また、演算部１ｂは、タスクβから関数ｆｕｎｃ２を呼び出すという呼び出し関係を第１のオブジェクトファイル４ａから取得する。すると、例えば、演算部１ｂは、関数ｆｕｎｃ２のサイクル数を第２のオブジェクトファイル５ａから取得する。演算部１ｂは、タスクβおよび関数ｆｕｎｃ２について第１のオブジェクトファイル４ａおよび第２のオブジェクトファイル５ａから取得したサイクル数の合計をタスクβの実行に要するサイクル数（タスクβ全体のサイクル数といってもよい）とする。
【００２８】
第１のオブジェクトファイル４ａおよび第２のオブジェクトファイル５ａに対する上記のリンク処理は、演算部１ｂによって実現されるリンカ３によって実行されてもよい。こうして、演算部１ｂは、タスクαについて、呼び出し先関数ｆｕｎｃ１のサイクル数を含めた全体のサイクル数を取得できる。また、演算部１ｂは、タスクβについて、呼び出し先関数ｆｕｎｃ２のサイクル数を含めた全体のサイクル数を取得できる。
【００２９】
図２は、第１のソースプログラムの例を示す図である。
図２では、一例としてＣ言語を用いて第１のソースプログラム４を記述する場合を示している。ソースプログラムにおいて、タスクは、所定の指示文によって指定されることがある。指示文としては、例えば、ＯｐｅｎＭＰ（登録商標）の構文を用いることが可能である。図２の例では、ＯｐｅｎＭＰで、それぞれスレッド数が４，４である２つの並列タスクを表現するサンプルコードを例示している。なお、図２において、左側に付されている番号は行番号である（以降の図でも同様にして行番号を図示することがある）。なお、３以上の並列タスクも同様に表現され得る。
【００３０】
例えば、１０行目〜１２行目はタスクαの定義箇所である。また、１５行目〜１７行目はタスクβの定義箇所である。各タスクの定義箇所は、実行文や実行文を内部にもつループ構文および関数呼び出しを含み得る。各タスクは関数内で定義される。また、関数内では別の関数が呼び出されることがあり入れ子構造になる。
【００３１】
図３は、第２のソースプログラムの例を示す図である。
図３でも、図２と同様に、一例としてＣ言語を用いて第２のソースプログラム５を記述する場合を示している。第２のソースプログラム５は、関数ｆｕｎｃ１，ｆｕｎｃ２それぞれの定義を含む。
【００３２】
ところで、実行可能ファイルによって並列タスクの実行を開始する際には、スレッドを立ち上げて実行する。ここでは、プロセッサの１コア当たり１つのスレッドを実行する場合を考える。このとき、並列に実行可能な各タスクに割り当てるコア数によっては、あるタスクの実行が他のタスクよりも早く終了することがある。すると、タスクの実行を終了したコアが、他のタスクの実行が終了するまで待機することになり、当該コアが処理を何も実行しない空き状態になり効率的ではない。
【００３３】
例えば、並列タスクを効率的に実行するには、各タスクの実行時間が均等になるように各タスクへのコア数の割り当てを行うことが望ましい。コア数の割り当てを行うための情報として、各タスクのコスト（サイクル数）と並列実行可能性が考えられる。しかし、プログラムは、一般的に複数のソースファイルを含み得る。この場合、コンパイル時には、タスク全体のサイクル数の情報を得ることが難しい。コンパイルはソースファイル毎に行われるため、あるタスクの呼び出し先の関数が異なるソースファイルに定義されていると、当該関数内のサイクル数がコンパイラ２には分からないためである。タスクから呼び出される関数を１つのファイルにまとめるために、複数のソースファイルを１つのファイルに結合してからコンパイルする方法も考えられる。しかし、この方法では、プログラムの一部に修正を行う度に、結合後のファイルを再コンパイルすることになり、手間が増える。更に、各ソースファイルを１つにまとめるとファイルサイズが大きくなり、コンパイル時のメモリ使用負荷も大きくなってしまう。
【００３４】
例えば、図２，３に示すように、並列タスクを含み、かつ、複数のソースファイルで構成されるプログラムでは、タスクのスレッド数を割り当てる部分とタスクの定義部分とが別のファイルに存在する。具体的には、タスクαは、関数ｆｕｎｃ１を呼び出す。関数ｆｕｎｃ１は、１０００回転のループを含む。タスクβは、関数ｆｕｎｃ２を呼び出す。関数ｆｕｎｃ２は、１０回転のループを含む。両者のコストには差がある。仮に、タスクα，βの両方を同じスレッド数で実行したならば、１０回転のループを実行するタスクβが先に終わり、１０００回転のループを実行するタスクαが終了するまで待ちが生じることになる。この場合、１０００回転のループを含むタスクαに対して、タスクβよりも多くのスレッド数を割り当てれば、待ち時間が短くて済み効率的である。しかし、コンパイラは、１つのファイル毎にコンパイルを行うため、ファイル間を跨いだタスクのコストを解析することが難しい。このため、各タスクのコストに応じて自動的にスレッド数を調整することが難しい。
【００３５】
そこで、計算機１は、ソースプログラムのコンパイルの際に、ソースプログラムに含まれる関数毎の実行に要するサイクル数とタスクおよび関数の呼び出し関係とを示す情報を生成する。計算機１は、リンク処理の際に、サイクル数および呼び出し関係に基づいてタスク毎の実行に要するサイクル数を算出する。例えば、計算機１は、生成したサイクル数および呼び出し関係の情報を、オブジェクトファイルに追加する。計算機１は、リンク処理の際に、各オブジェクトファイルに含まれるサイクル数および呼び出し関係の情報に基づいて、タスク毎のサイクル数を適切に取得できる。その結果、計算機１は、取得したタスク毎のサイクル数を基に、各タスクへのスレッド数の割り当てを行えるようになる。
【００３６】
［第２の実施の形態］
第２の実施の形態の情報処理装置は、コンパイラおよびリンカを用いて、Ｃ言語などの高級言語で記述されたソースコードから実行コードを生成する。
【００３７】
図４は、第２の実施の形態の情報処理装置のハードウェア例を示す図である。
情報処理装置１００は、ＣＰＵ１０１，１０２、ＲＡＭ１０３、ＨＤＤ１０４、画像信号処理部１０５、入力信号処理部１０６、媒体リーダ１０７および通信インタフェース１０８を有する。これらのハードウェアユニットは、情報処理装置１００内でバスに接続されている。ＣＰＵ１０１，１０２は、第１の実施の形態の演算部１ｂの一例であり、ＲＡＭ１０３またはＨＤＤ１０４は、第１の実施の形態の記憶部１ａの一例である。
【００３８】
ＣＰＵ１０１，１０２は、プログラムの命令を実行する１または２以上のコアを含むプロセッサである。例えば、ＣＰＵ１０１は、コア１０１ａ，１０１ｂを含む複数のコアを有する。同一または異なるＣＰＵに属する複数のコアは、互いに並列に命令を実行できる。ＣＰＵ１０１，１０２は、ＨＤＤ１０４に記憶されているプログラムやデータの少なくとも一部をＲＡＭ１０３にロードし、プログラムを実行する。なお、各コアを「プロセッサ」と呼んでもよいし、複数のプロセッサの集合を「プロセッサ」（マルチプロセッサ）と呼んでもよい。情報処理装置１００は、ＣＰＵ１０１，１０２に加えて、更に１以上のＣＰＵを備えてもよい。また、第２の実施の形態の例では、１つのコア当たり同時に複数のスレッドを実行する場合ではなく、１つのコア当たり１つのスレッドを実行する場合を考える。
【００３９】
ＲＡＭ１０３は、ＣＰＵ１０１，１０２が実行するプログラムやＣＰＵ１０１，１０２が演算に用いるデータを一時的に記憶する揮発性メモリである。なお、情報処理装置１００は、ＲＡＭ以外の種類のメモリを備えてもよく、複数個のメモリを備えてもよい。
【００４０】
ＨＤＤ１０４は、ＯＳ（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）、半導体メモリなどを使用できる。媒体リーダ１０７は、例えば、記録媒体１３から読み取ったプログラムやデータをＲＡＭ１０３またはＨＤＤ１０４に格納する。
【００４４】
通信インタフェース１０８は、ネットワーク１４に接続され、ネットワーク１４を介して他の情報処理装置と通信を行うインタフェースである。通信インタフェース１０８は、スイッチなどの通信装置とケーブルで接続される有線通信インタフェースでもよいし、基地局と無線リンクで接続される無線通信インタフェースでもよい。
【００４５】
なお、情報処理装置１００が備えるＣＰＵの数は１個でもよい。また、情報処理装置１００は、媒体リーダ１０７を備えていなくてもよい。また、情報処理装置１００は、ユーザが操作する端末装置からネットワーク１４経由で制御される場合には、画像信号処理部１０５や入力信号処理部１０６を備えていなくてもよい。また、情報処理装置１００は、通信インタフェース１０８を備えていなくてもよい。また、ディスプレイ１１や入力デバイス１２が、情報処理装置１００の筐体と一体に形成されていてもよい。
【００４６】
図５は、情報処理装置のソフトウェア例を示す図である。
情報処理装置１００は、ソースファイル記憶部１１０、オブジェクトファイル記憶部１２０、実行可能ファイル記憶部１３０、コンパイラ１４０およびリンカ１５０を有する。ソースファイル記憶部１１０、オブジェクトファイル記憶部１２０および実行可能ファイル記憶部１３０は、例えば、ＲＡＭ１０３またはＨＤＤ１０４に確保された記憶領域として実装される。コンパイラ１４０およびリンカ１５０は、例えば、ＣＰＵ１０１，１０２が実行するソフトウェアのモジュールとして実装される。
【００４７】
ソースファイル記憶部１１０は、ソースファイルを記憶する。ソースファイルは、Ｃ言語などの高級言語を用いて記述されたソースプログラム（ソースコードということもある）を含むファイルである。ソースファイルは、ユーザが入力デバイス１２を用いて作成したものでもよいし、他の情報処理装置からネットワーク１４経由で情報処理装置１００に送信されたものでもよい。
【００４８】
オブジェクトファイル記憶部１２０は、オブジェクトファイルを記憶する。オブジェクトファイルは、ＣＰＵが直接理解できる機械語を用いて記述されたオブジェクトコードを含むファイルである。オブジェクトコードは、ソースプログラムをコンパイルすることで生成される。
【００４９】
実行可能ファイル記憶部１３０は、実行可能ファイルを記憶する。実行可能ファイルは、実行可能形式のプログラムモジュールであり、オブジェクトファイルから生成される。実行可能ファイルは、複数のオブジェクトファイルを結合することで生成されることもある。実行可能ファイルは、情報処理装置１００で実行されてもよいし、他の情報処理装置に送信されて当該他の情報処理装置で実行されてもよい。
【００５０】
コンパイラ１４０は、ソースファイル記憶部１１０からソースファイルを取得し、ソースファイルに含まれるソースプログラムをコンパイルする。そして、コンパイラ１４０は、ソースプログラムに対応するオブジェクトコードを生成し、生成したオブジェクトコードを含むオブジェクトファイルをオブジェクトファイル記憶部１２０に格納する。コンパイラ１４０は、ループ並列性解析部１４１、タスク範囲抽出部１４２、関数コスト解析部１４３、関数呼び出し抽出部１４４および関数情報追加部１４５を有する。
【００５１】
ループ並列性解析部１４１は、ソースプログラムを解析して、ソースプログラムに含まれる演算命令および演算命令の実行順序に基づいて、関数内のループ処理を特定する。ループ並列性解析部１４１は、各ループが繰り返し毎に並列処理可能であるか否かを判定し、ループ毎に並列処理可能か否かを示すループ並列性情報を生成してＲＡＭ１０３に格納する。例えば、ループで繰り返し実行される各処理を独立に実行できる場合（例えば、前回以前の処理結果の影響を受けない、次回以降の処理結果に影響を与えないなど）、当該ループは並列に実行可能である。より具体的には、１００回転のループがある場合、１から５０回転分および５１から５０回転分を異なる２つのスレッドによって並列に実行可能である（３以上のスレッドで並列実行することもできる）。
【００５２】
タスク範囲抽出部１４２は、ソースプログラムを解析して、ＯｐｅｎＭＰ指示文などで指定された並列に動作するタスクの開始・終了位置を把握する。また、タスク範囲抽出部１４２は、ソースプログラムに対して生成されたオブジェクトファイル内の命令列の、スレッド数指定命令の直前にラベルを挿入する。当該ラベルは、並列タスクの実行箇所をリンカ１５０により識別可能とするためのものである。タスク範囲抽出部１４２は、並列タスクの開始・終了位置およびラベル名をタスク範囲情報として抽出し、ＲＡＭ１０３に格納する。
【００５３】
関数コスト解析部１４３は、関数のコストを見積もる。関数コスト解析部１４３は、タスク範囲抽出部１４２でタスクが検出された場合は検出した各タスク範囲のコストを見積もる。コストとは、ソースプログラムの関数またはタスク範囲に対応する命令列に含まれる各命令の実行に要するクロックサイクル数の総和である。クロックサイクル数を、単にサイクル数と称することがある。ここで、例えば、オブジェクトファイル記憶部１２０には、命令とサイクル数の対応関係の情報が予め格納される。関数コスト解析部１４３は、当該対応関係の情報を基に、各命令のサイクル数を特定できる。
【００５４】
ループの場合は、ループ内の命令列のコストにループの回転数を乗じたものが当該ループのコストである。なお、ループの回転数が不明の場合には、特開２００６−２９３７６８号公報に開示の方法により、ループ内に現れる配列の要素数や固定値（例えば、１００など）を用いてもよい。ループ並列性情報に、対象のループが並列化可能であることが示されている場合、関数コスト解析部１４３は、上記の方法で求めたコストをスレッド数で割った値をループのコストとする。このため、コストは割り当てられるスレッド数をパラメータとしてもつ。関数コスト解析部１４３は、求めたコストを関数コスト情報としてＲＡＭ１０３に格納する。
【００５５】
関数呼び出し抽出部１４４は、ソースプログラムを解析して、関数の呼び出し関係を抽出する。関数の呼び出し関係は、呼び出した関数名および呼び出し回数の情報を含む。タスク範囲抽出部１４２によりタスク範囲が検出されている場合は、検出したタスク毎に関数の呼び出し関係を抽出する。関数呼び出し抽出部１４４は、抽出した情報を関数呼び出し情報としてＲＡＭ１０３に格納する。
【００５６】
関数情報追加部１４５は、タスク範囲抽出部１４２によって生成されたタスク範囲情報、関数コスト解析部１４３によって生成された関数コスト情報、および、関数呼び出し抽出部１４４によって生成された関数呼び出し情報を、オブジェクトファイルに追加する。ただし、追加するタスク範囲情報は、スレッド数指定命令直前のラベル名のみでよい。オブジェクトファイルに追加されるこれらの各情報は、後述するように関数またはタスク単位に追加されることになる。
【００５７】
リンカ１５０は、オブジェクトファイル記憶部１２０からオブジェクトファイルを取得し、オブジェクトファイルに含まれるオブジェクトコードから参照される他のオブジェクトファイルやライブラリを検索する。そして、リンカ１５０は、オブジェクトファイルと他のオブジェクトファイルやライブラリとを結合し、実行可能ファイルを生成し、実行可能ファイル記憶部１３０に格納する。ここで、リンカ１５０は、以下に示す各部の処理が行われた後のオブジェクトファイルを用いて、リンク処理を行う。リンカ１５０は、関数情報取得部１５１、タスク範囲解析部１５２、関数呼び出し解析部１５３、タスクコスト解析部１５４、スレッド数判定部１５５およびスレッド数変更部１５６を有する。
【００５８】
関数情報取得部１５１は、結合対象の全てのオブジェクトファイルから、コンパイル時に埋め込まれたタスク範囲情報と関数コスト情報と関数呼び出し情報を取得する。
タスク範囲解析部１５２は、タスク範囲情報からタスクのラベル名を取得する。ラベル名が存在しない場合は、並列なタスクが存在しないため、以降の解析を実行しなくてよい（通常通り実行可能ファイルが生成されることになる）。
【００５９】
関数呼び出し解析部１５３は、関数呼び出し情報に基づいて、各タスクからの関数呼び出し関係を構築する。
タスクコスト解析部１５４は、各タスクのコストを解析する。タスクコスト解析部１５４は、関数呼び出し解析部１５３によって構築された関数呼び出し関係に基づいて、タスクから呼び出されている全ての関数のコストを集める。タスクコスト解析部１５４は、該当のタスクから呼び出されている全ての関数のコストを考慮に入れた当該タスクの総コストを、実行スレッド数をパラメータとして表わす。
【００６０】
具体的には、タスクまたは関数の名前をｔ、実行するスレッド数をｎとして、当該タスクの総コストをＡｌｌＣ（ｔ，ｎ）で表わす。また、タスクまたは関数ｔから呼び出されている関数内のコストを含まないコストをＣ（ｔ，ｎ）で表わす。Ｃ（ｔ，ｎ）は、関数コスト情報である。このとき、タスクまたは関数ｔから直接呼び出される関数をｆｕｎｃとすると、ＡｌｌＣ（ｔ，ｎ）は、Ｃ（ｔ，ｎ）＋Σ｛ＡｌｌＣ（ｆｕｎｃ，ｎ）×（ｔからｆｕｎｃを呼び出す回数）｝である。ここで、Σは、タスクまたは関数ｔから直接呼び出される全ての関数について総和をとることを意味する。
【００６１】
スレッド数判定部１５５は、タスクコスト解析部１５４によるタスク毎のコストの解析結果に基づいて、各タスクの終了時刻の差が小さくなるように各タスクに割り当てるスレッド数を求める。具体的には、スレッド数判定部１５５は、各タスクのスレッド数の初期値を１にする。タスクの総スレッド数が利用可能なコア数未満であれば、各タスクを現割り当てスレッド数で実行する際の総コストを求める。そして、スレッド数判定部１５５は、総コストが最も高いタスクに対してスレッド数を１増やす。これをスレッド総数が利用可能なコア数と等しくなるまで繰り返して各タスクのスレッド数を求める。
【００６２】
スレッド数変更部１５６は、オブジェクトファイルの中のスレッド数の設定を書き換える。スレッド数変更部１５６は、オブジェクトファイル内でラベル名を検索し、直後の命令（スレッド数を指定する命令）の内容を変更する。すなわち、スレッド数変更部１５６は、当該命令内でタスクを起動するスレッド数を定めるレジスタに対して、スレッド数判定部１５５が求めたスレッド数の値を代入するように命令を変更する。スレッド数変更部１５６は、変更対象の命令に対して、どのような変更を施せばスレッド数の値が変わるのかといった情報を予め把握している。
【００６３】
図６は、ファイルの例を示す図である。
第２の実施の形態では、以下のファイルを例示する。ソースファイル１１１，１１２，１１３，１１４は、ソースファイル記憶部１１０に記憶される。ソースファイル１１１のファイル名は、“ｍａｉｎ．ｃ”である。ソースファイル１１２のファイル名は、“ｓｕｂ１．ｃ”である。ソースファイル１１３のファイル名は、“ｓｕｂ２．ｃ”である。ソースファイル１１４のファイル名は、“ｓｕｂ３．ｃ”である。
【００６４】
コンパイラ１４０は、ソースファイル１１１，１１２，１１３，１１４をコンパイルして、オブジェクトファイル１２１，１２２，１２３，１２４を生成し、オブジェクトファイル記憶部１２０に格納する。オブジェクトファイル１２１は、ソースファイル１１１のコンパイル結果である。オブジェクトファイル１２１のファイル名は、“ｍａｉｎ．ｏ”である。オブジェクトファイル１２２のファイル名は、“ｓｕｂ１．ｏ”である。オブジェクトファイル１２３のファイル名は、“ｓｕｂ２．ｏ”である。オブジェクトファイル１２４のファイル名は“ｓｕｂ３．ｏ”である。
【００６５】
リンカ１５０は、オブジェクトファイル１２１，１２２，１２３，１２４を結合して、実行可能ファイル１３１を生成し、実行可能ファイル記憶部１３０に格納する。
次に、ソースファイル１１１，１１２，１１３，１１４に含まれるソースプログラムを例示する。以下では、一例としてＣ言語による記述を示す。
【００６６】
図７は、ソースプログラムの例（その１）を示す図である。
例えば、ソースファイル１１１には、関数ｍａｉｎが含まれる。ソースファイル１１１のコンパイルの際、ループ並列性解析部１４１は、関数ｍａｉｎ内で並列可能なループを探すが、関数ｍａｉｎには並列可能なループは存在していない。更に、タスク範囲抽出部１４２は、ソースファイル１１１内にタスクが定義されていることを検出し、開始位置と終了位置を記憶する。具体的には、ソースファイル１１１には、１２行目〜１４行目に１つ目のタスクが、１７行目〜１９行目に２つ目のタスクが記述されている。１つ目のタスクをタスクＡとする。２つ目のタスクをタスクＢとする。ソースファイル１１１の１１行目の記述“＃ｐｒａｇｍａ  ｏｍｐ  ｐａｒａｌｌｅｌ  ｎｕｍ＿ｔｈｒｅａｄｓ（４）”は、タスクＡのスレッド数の指定である。同１６行目の記述“＃ｐｒａｇｍａ  ｏｍｐ  ｐａｒａｌｌｅｌ  ｎｕｍ＿ｔｈｒｅａｄｓ（２）”は、タスクＢのスレッド数の指定である。
【００６７】
この例では、タスクＡ，Ｂを並列に実行可能であり、ソースプログラムを記述したユーザによって、タスクＡのスレッド数を４、タスクＢのスレッド数を２として実行することが記述されている。ただし、ユーザによって指定されたスレッド数は、情報処理装置１００によって調整され得る。
【００６８】
タスクＡは、関数ｆｕｎｃ１の呼び出しを含む（１３行目の“ｆｕｎｃ１（ｉｎｐｕｔ，ａ＿ｏｕｔ）”）。タスクＢは、関数ｆｕｎｃ２の呼び出しを含む（１８行目の“ｆｕｎｃ２（ｉｎｐｕｔ，ｂ＿ｏｕｔ）”）。
【００６９】
関数コスト解析部１４３は、タスクＡ，Ｂに含まれる各命令のコストの和を算出する。図７の例では、タスクＡ，Ｂの双方ともに関数呼び出し命令のコストのみである。また、関数呼び出し抽出部１４４は、タスクＡから関数ｆｕｎｃ１を呼び出すという関数呼び出し情報、および、タスクＢから関数ｆｕｎｃ２を呼び出すという関数呼び出し情報を生成する。
【００７０】
図８は、ソースプログラムの例（その２）を示す図である。
図８（Ａ）は、ソースファイル１１２に含まれるソースプログラムの例を示す。図８（Ｂ）は、ソースファイル１１３に含まれるソースプログラムの例を示す。図８（Ｃ）は、ソースファイル１１４に含まれるソースプログラムの例を示す。
【００７１】
例えば、ソースファイル１１２は、関数ｆｕｎｃ１の定義を含む。ソースファイル１１２のコンパイルの際、ループ並列性解析部１４１は、ソースファイル１１２から並列化可能なループを探す。関数ｆｕｎｃ１は、並列化可能なループを含む。ループ並列性解析部１４１は、関数ｆｕｎｃ１内の当該ループを並列化可能と特定する。
【００７２】
タスク範囲抽出部１４２は、タスクの定義を探すが、関数ｆｕｎｃ１にはタスクの定義が存在しないことを検出する。関数コスト解析部１４３は、関数ｆｕｎｃ１のコストを算出する。このとき、関数コスト解析部１４３は、スレッド数を表わすパラメータｎを用いて、並列化可能ループのコストを、ループ内の命令コスト×回転数／ｎとする。関数ｆｕｎｃ１は、他の関数の呼び出しを含まない。このため、関数呼び出し抽出部１４４は、関数ｆｕｎｃ１から他の関数の呼び出しがないことを検出する。
【００７３】
ソースファイル１１３は、関数ｆｕｎｃ２の定義を含む。関数ｆｕｎｃ２は、並列化可能なループを含む。ソースファイル１１３のコンパイルの際、ループ並列性解析部１４１は、ソースファイル１１２の場合と同様に、関数ｆｕｎｃ２内の当該ループを並列化可能と判断する。また、タスク範囲抽出部１４２は、タスクの定義を探すが、関数ｆｕｎｃ２にはタスクの定義が存在しないことを検出する。関数コスト解析部１４３は、ソースファイル１１２の場合と同様に、関数ｆｕｎｃ２のコストを算出する。更に、関数ｆｕｎｃ２は、関数ｆｕｎｃ３の呼び出しを含む。このため、関数呼び出し抽出部１４４は、関数ｆｕｎｃ２から関数ｆｕｎｃ３の呼び出しがあることを検出する。
【００７４】
ソースファイル１１４は、関数ｆｕｎｃ３の定義を含む。関数ｆｕｎｃ３は、並列化不可能なループを含む。ソースファイル１１４のコンパイルの際、ループ並列性解析部１４１は、関数ｆｕｎｃ３内の当該ループを並列化不可能と特定する。タスク範囲抽出部１４２は、タスクの定義を探すが、関数ｆｕｎｃ３にはタスクの定義が存在しないことを検出する。また、関数コスト解析部１４３は、関数ｆｕｎｃ３のコストを算出する。関数ｆｕｎｃ３内のループは並列化不可能であるので、ループのコストを、ループ内の命令コスト×回転数となる。更に、関数ｆｕｎｃ３は、他の関数の呼び出しを含まない。このため、関数呼び出し抽出部１４４は、関数ｆｕｎｃ３から他の関数の呼び出しがないことを検出する。
【００７５】
図９は、関数に対する命令列の例を示す図である。
図９（Ａ）は、関数ｍａｉｎに対する命令列の例を示している。図９（Ｂ）は、関数ｆｕｎｃ１に対する命令列の例を示している。これらの命令列は、コンパイラ１４０によって生成されるオブジェクトコードの一部と考えてもよい。
【００７６】
図９（Ａ）において、例えば、関数ｍａｉｎに対する命令列は、タスクＡ，Ｂそれぞれの命令列を含む。例えば、タスクの先頭およびタスクの末尾は、タスクの先頭およびタスクの末尾を示す所定のコードによって特定され得る。１番目のタスク範囲（図９（Ａ）の１行目から３行目まで）は、タスクＡの命令列である。２番目のタスク範囲（図９（Ａ）の４行目から６行目まで）は、タスクＢの命令列である。この例では、タスクＡ，Ｂは、コストの計算対象となる命令として、関数呼び出し命令のみを含む。例えば、コンパイラ１４０内部での関数呼び出しがｃａｌｌ命令により表現される。すると、このｃａｌｌ命令のサイクル数が、タスクＡ，Ｂ内の命令のコストである。
【００７７】
図９（Ｂ）において、例えば、関数ｆｕｎｃ１に対する命令列は、回転数が１００のループ処理を示す。関数ｆｕｎｃ１の当該ループは、並列化可能なループである。例えば、ループの先頭およびループの末尾は、ループの先頭およびループの末尾を示す所定のコードによって特定され得る。このループは、ｌｏａｄ命令とａｄｄ命令とｓｔｏｒｅ命令の３つを繰り返し実行する。すると、関数ｆｕｎｃ１のコストは、ｌｏａｄ命令のサイクル数とａｄｄ命令のサイクル数とｓｔｏｒｅ命令のサイクル数の和にループ回転数１００を乗じ、更にスレッド数ｎで割った値となる。
【００７８】
図１０は、サイクル数テーブルの例を示す図である。
サイクル数テーブル１２５は、例えばオブジェクトファイル記憶部１２０に予め格納される。サイクル数テーブル１２５は、命令およびサイクル数の項目を含む。
【００７９】
命令の項目には、命令が登録される。サイクル数の項目には、命令の実行に要するサイクル数が登録される。例えば、サイクル数テーブル１２５には、命令が“ｓｔｏｒｅ”、サイクル数が“１０”という情報が登録される。これは、ｓｔｏｒｅ命令の実行に要するサイクル数（クロックサイクル数）が１０であることを示す。
【００８０】
図１１は、タスク範囲情報の例を示す図である。
タスク範囲情報１２１ａは、オブジェクトファイル１２１に追加されるタスク範囲情報を例示している。タスク範囲情報１２１ａは、タスクＡに対するラベル名、および、タスクＢに対するラベル名を含む。ソースファイル１１１が３以上のタスクを含む場合には、タスク範囲情報１２１ａは３以上のラベル名を含むことになる。
【００８１】
オブジェクトファイル１２２，１２３，１２４も同様のタスク範囲情報を含む。ただし、ソースファイル１１２，１１３，１１４において、タスクが検出されない場合は、タスク範囲情報には何れのラベル名も含まれないことになる（設定なしとなる）。
【００８２】
図１２は、関数コスト情報の例を示す図である。
関数コスト情報１２１ｂは、オブジェクトファイル１２１に追加される関数コスト情報を例示している。関数コスト情報１２１ｂは、前述のように、タスクまたは関数において呼び出し先の関数のコストを含まないコストＣ（ｔ，ｎ）を含む。
【００８３】
Ｃ（ｔ，ｎ）＝Ｓｃ１＋Ｓｃ２＋Ｓｃ３（ｎ）である。Ｓｃ１は、ループ以外の命令のサイクル数の総和である。Ｓｃ２は、並列化不可能なループのループ内命令のサイクル数の総和×ループ回転数である。Ｓｃ３は、並列化可能なループのループ内命令のサイクル数の総和×ループ回転数／ｎである。ｎは、スレッド数を示すパラメータである。
【００８４】
前述のタスクＡの例では、次のようになる。タスクＡは、ループ以外の命令として、ｃａｌｌ命令を１つだけ含むので、Ｓｃ１＝２である。タスクＡは、並列化不可能なループを含まないのでＳｃ２＝０である。タスクＡは、並列化可能なループを含まないのでＳｃ３（ｎ）＝０である。よって、Ｃ（タスクＡ，ｎ）＝２＋０＋０／ｎ＝２である。
【００８５】
オブジェクトファイル１２２，１２３，１２４も同様の関数コスト情報を含む。例えば、図９（Ｂ）およびサイクル数テーブル１２５の例によれば、ｌｏａｄ命令のサイクル数が１０、ａｄｄ命令のサイクル数が１、ｓｔｏｒｅ命令のサイクル数が１０である。したがって、関数ｆｕｎｃ１では、Ｓｃ３（ｎ）＝（１０＋１＋１０）×１００／ｎ＝２１００／ｎである。また、Ｓｃ１＝Ｓｃ２＝０である。よって、関数コスト解析部１４３は、関数ｆｕｎｃ１のコストをＣ（ｆｕｎｃ１，ｎ）＝２１００／ｎと見積もることになる。関数ｆｕｎｃ１の関数コスト情報は、オブジェクトファイル１２２に追加される。
【００８６】
なお、関数コスト解析部１４３は、コストへの寄与の小さい項を無視してもよい（例えば、前述のＳｃ１に相当する項がＳｃ２やＳｃ３（ｎ）に相当する項に比べて微少であれば、Ｓｃ１に相当する項を０とみなしてもよい）。
【００８７】
図１３は、関数呼び出し情報の例を示す図である。
関数呼び出し情報１２１ｃは、オブジェクトファイル１２１に追加される関数呼び出し情報を例示している。関数呼び出し情報１２１ｃは、呼び出し元のタスクまたは関数名、呼び出し先の関数名および呼び出し回数の情報を含む。例えば、タスクＡでは、関数ｆｕｎｃ１を１回呼び出す。したがって、関数呼び出し情報１２１ｃは、呼び出し元のタスク名が“タスクＡ”、呼び出し先の関数名が“ｆｕｎｃ１”、呼び出し回数が“１”という情報を含むことになる。オブジェクトファイル１２２，１２３，１２４も同様の関数呼び出し情報を含む。ただし、他の関数の呼び出しを含まない場合は、関数呼び出し情報として、呼び出しがないという情報が登録されることになる。
【００８８】
図１４は、オブジェクトファイルの例（その１）を示す図である。
オブジェクトファイル１２１は、通常時のｍａｉｎ．ｃに対するオブジェクト情報（オブジェクトコードの情報）に加えて、関数ｍａｉｎの関数情報を含む。関数ｍａｉｎの関数情報は、下記のタスク範囲情報（タスク範囲情報１２１ａ）、関数コスト情報（関数コスト情報１２１ｂ）、および、関数呼び出し情報（関数呼び出し情報１２１ｃ）を含む。
【００８９】
タスク範囲情報は、タスクＡのラベル名“．ｇｌｏｂａｌ  ｔａｓｋ  ００１”を含む。タスク範囲情報は、タスクＢのラベル名“．ｇｌｏｂａｌ  ｔａｓｋ  ００２”を含む。
【００９０】
関数コスト情報は、タスクＡに関する関数コスト情報Ｃ（タスクＡ，ｎ）を含む。関数コスト情報は、タスクＢに関する関数コスト情報Ｃ（タスクＢ，ｎ）を含む。
関数呼び出し情報は、“タスクＡでｆｕｎｃ１を１回呼び出し”という情報を含む。これは、タスクＡが関数ｆｕｎｃ１を１回呼び出すことを示す。関数呼び出し情報は、“タスクＢでｆｕｎｃ２を１回呼び出し”という情報を含む。これは、タスクＢが関数ｆｕｎｃ２を１回呼び出すことを示す。
【００９１】
図１５は、オブジェクトファイルの例（その２）を示す図である。
オブジェクトファイル１２２は、通常時のｓｕｂ１．ｃに対するオブジェクト情報に加えて、関数ｆｕｎｃ１の関数情報を含む。関数ｆｕｎｃ１の関数情報は、下記のタスク範囲情報、関数コスト情報、および、関数呼び出し情報を含む。
【００９２】
タスク範囲情報は、タスク範囲なしを示す情報（“なし”）を含む。関数コスト情報は、関数ｆｕｎｃ１に関する関数コスト情報Ｃ（ｆｕｎｃ１，ｎ）を含む。関数呼び出し情報は、関数呼び出しなしを示す情報（“関数呼び出しなし”）を含む。
【００９３】
オブジェクトファイル１２３は、通常時のｓｕｂ２．ｃに対するオブジェクト情報に加えて、関数ｆｕｎｃ２の関数情報を含む。関数ｆｕｎｃ２の関数情報は、下記のタスク範囲情報、関数コスト情報、および、関数呼び出し情報を含む。
【００９４】
タスク範囲情報は、タスク範囲なしを示す情報（“なし”）を含む。関数コスト情報は、関数ｆｕｎｃ２に関する関数コスト情報Ｃ（ｆｕｎｃ２，ｎ）を含む。関数呼び出し情報は、“ｆｕｎｃ２でｆｕｎｃ３を１回呼び出し”という情報を含む。これは、関数ｆｕｎｃ２が関数ｆｕｎｃ３を１回呼び出すことを示す。
【００９５】
オブジェクトファイル１２４は、通常時のｓｕｂ３．ｃに対するオブジェクト情報に加えて、関数ｆｕｎｃ３の関数情報を含む。関数ｆｕｎｃ３の関数情報は、下記のタスク範囲情報、関数コスト情報、および、関数呼び出し情報を含む。
【００９６】
タスク範囲情報は、タスク範囲なしを示す情報（“なし”）を含む。関数コスト情報は、関数ｆｕｎｃ３に関する関数コスト情報Ｃ（ｆｕｎｃ３，ｎ）を含む。関数呼び出し情報は、関数呼び出しなしを示す情報（“関数呼び出しなし”）を含む。
【００９７】
図１６は、タスクおよび関数の呼び出し関係の例を示す図である。
関数呼び出し解析部１５３は、オブジェクトファイル１２１，１２２，１２３，１２４に追加された関数呼び出し情報に基づいて、タスクおよび関数の呼び出し関係を把握する。例えば、関数呼び出し解析部１５３は、オブジェクトファイル１２１に含まれる関数呼び出し情報に基づいて、タスクＡから関数ｆｕｎｃ１が１回呼び出されることを把握する。関数呼び出し解析部１５３は、オブジェクトファイル１２２に含まれる関数ｆｕｎｃ１の関数呼び出し情報から、関数ｆｕｎｃ１からは他の関数の呼び出しがないことを把握する。
【００９８】
更に、関数呼び出し解析部１５３は、オブジェクトファイル１２１に含まれる関数呼び出し情報に基づいて、タスクＢから関数ｆｕｎｃ２が１回呼び出されることを把握する。関数呼び出し解析部１５３は、オブジェクトファイル１２３に含まれる関数呼び出し情報に基づいて、関数ｆｕｎｃ２から関数ｆｕｎｃ３が１回呼び出されることを把握する。関数呼び出し解析部１５３は、オブジェクトファイル１２４に含まれる関数呼び出し情報に基づいて、関数ｆｕｎｃ３からは他の関数の呼び出しがないことを把握する。
【００９９】
図１７は、タスクコストテーブルの例を示す図である。タスクコストテーブル１３２は、タスクコスト解析部１５４によって作成され、オブジェクトファイル記憶部１２０に格納される。タスクコストテーブル１３２は、タスク毎に計算されたタスク全体のコスト（スレッド数を示すパラメータを含む）を管理するためのテーブルである。タスクコストテーブル１３２は、タスクおよびコストの項目を含む。
【０１００】
タスクの項目には、タスク名が登録される。コストの項目には、当該タスク全体のコストＡｌｌＣ（ｔ，ｎ）が登録される。例えば、タスクコストテーブル１３２には、タスクが“タスクＡ”、コストが“（２１００／ｎ）＋２”という情報が登録される。これは、タスクＡの全体のコストが、スレッド数ｎをパラメータとして、（２１００／ｎ）＋２で表わされることを示す。なお、図１７では、スレッド数を示すパラメータをｎ，ｍとしてタスク毎に区別して用いる。
【０１０１】
ここで、前述のように、タスクＡ全体のコストＡｌｌＣ（タスクＡ，ｎ）は、Ｃ（タスクＡ，ｎ）＋Σ｛ＡｌｌＣ（ｆｕｎｃ１，ｎ）×（タスクＡからｆｕｎｃ１を呼び出す回数）｝＝Ｃ（タスクＡ，ｎ）＋ＡｌｌＣ（ｆｕｎｃ１，ｎ）×１である。
【０１０２】
Ｃ（タスクＡ，ｎ）＝２である。また、ＡｌｌＣ（ｆｕｎｃ１，ｎ）＝Ｃ（ｆｕｎｃ１，ｎ）＝２１００／ｎである。よって、ＡｌｌＣ（タスクＡ，ｎ）＝（２１００／ｎ）＋２となる。
【０１０３】
タスクコストテーブル１３２には、タスクＢ全体のコストＡｌｌＣ（タスクＢ，ｍ）として、（１００００／ｍ）＋１０という情報も登録されている。ＡｌｌＣ（タスクＢ，ｍ）は、Ｃ（タスクＢ，ｍ）＋Ｃ（ｆｕｎｃ２，ｍ）×１＋Ｃ（ｆｕｎｃ３，ｍ）の計算結果である。
【０１０４】
スレッド数判定部１５５は、タスクコストテーブル１３２に登録されたタスクＡ，Ｂのコストに基づいて、タスクＡ，Ｂを並列に実行する際の、タスクＡ，Ｂに割り当てるスレッド数を決定する。
【０１０５】
図１８は、スレッド数の決定例を示す図である。
利用可能なコア数を８個とする。スレッド数判定部１５５は、ｎ＝１、ｍ＝１を初期値として、ＡｌｌＣ（タスクＡ，１）＝２１０２およびＡｌｌＣ（タスクＢ，１）＝１００１０を求める。コストの大きい方のタスクに割り当てるスレッド数を１追加し、ＡｌｌＣ（タスクＡ，ｎ）およびＡｌｌＣ（タスクＢ，ｍ）を計算し直す。これを、ｎ＋ｍ＝８となるまで繰り返し、最終的な（ｎ，ｍ）の組（ｎ，ｍ）＝（２，６）を取得する。この場合、スレッド数判定部１５５は、タスクＡに割り当てるスレッド数を２とする。また、スレッド数判定部１５５は、タスクＢに割り当てるスレッド数を６とする。
【０１０６】
図１９は、スレッド数の設定例を示す図である。
図１９（Ａ）は、スレッド数の設定前のオブジェクトファイル１２１を例示している。図１９（Ｂ）は、スレッド数の設定後のオブジェクトファイル１２１を例示している。スレッド数変更部１５６は、スレッド数判定部１５５が求めた各タスクのスレッド数をオブジェクトファイル１２１に設定する。
【０１０７】
例えば、オブジェクトファイル１２１内の命令列には、タスクＡを示すラベル“．ｇｌｏｂａｌ  ｔａｓｋ  ００１”、および、タスクＢを示すラベル“．ｇｌｏｂａｌ  ｔａｓｋ  ００２”が含まれる。スレッド数変更部１５６は、当該ラベルのラベル名を、オブジェクトファイル１２１のタスク範囲情報から取得できる。スレッド数変更部１５６は、各ラベルの直後の命令を、タスクを起動するスレッド数を定めるレジスタに、スレッド数判定部１５５が決定したスレッド数を代入するよう書き換える。
【０１０８】
例えば、スレッド数変更部１５６は、ラベル直後の命令の第１引数の値を、第２引数に代入しており、第２引数の値がスレッド数を表わすものであることを予め把握している。スレッド数変更部１５６は、まず、オブジェクト内からラベルを探し、スレッド数を変更するために、“．ｇｌｏｂａｌ  ｔａｓｋ  ００１”の直後の命令（２行目のｍｏｖ命令）の第１引数（“％レジスタ１”と表記）を２に変更する。また、スレッド数変更部１５６は、“．ｇｌｏｂａｌ  ｔａｓｋ  ００２”の直後の命令（７行目のｍｏｖ命令）の第１引数（“％レジスタ１”と表記）を６に変更する。この場合、第１引数の即値を設定することで、即値の代入を表わすものとする。
【０１０９】
次に、以上のような情報処理装置１００による処理手順を例示する。
図２０は、コンパイル処理の例を示すフローチャートである。以下、図２０に示す処理をステップ番号に沿って説明する。以下の手順は、１つのソースファイルのコンパイル毎に実行される。
【０１１０】
（Ｓ１１）ループ並列性解析部１４１は、ソースファイルに含まれるソースプログラムの先頭の関数に進む。具体的には、ループ並列性解析部１４１は、ソースプログラムの構文を解析することで、先頭に記述された関数を特定する。
【０１１１】
（Ｓ１２）ループ並列性解析部１４１は、ソースプログラムの構文を解析して、着目する関数内のループが繰り返し毎に並列処理可能かを解析する。例えば、ループで繰り返し実行される各処理を独立に実行できる場合（例えば、前回以前の処理結果の影響を受けない、次回以降の処理結果に影響を与えないなど）、当該ループは並列に実行可能である。ループ並列性解析部１４１は、該当のループが並列処理可能か否かを示す情報をＲＡＭ１０３に格納する。なお、関数内にループが含まれない場合は、ステップＳ１２をスキップしてステップＳ１３に進めてよい。
【０１１２】
（Ｓ１３）ループ並列性解析部１４１は、ソースプログラム中にループ並列性を未解析の関数があるか否かを判定する。未解析の関数がある場合、処理をステップＳ１４に進める。未解析の関数がない場合、処理をステップＳ１５に進める。
【０１１３】
（Ｓ１４）ループ並列性解析部１４１は、解析対象を次の関数に進める（着目する関数が次の関数となる）。そして、処理をステップＳ１２に進める。
（Ｓ１５）コンパイラ１４０は、ソースプログラムに相当する命令列を生成する。
【０１１４】
（Ｓ１６）タスク範囲抽出部１４２は、先頭の関数に処理を進める。具体的には、タスク範囲抽出部１４２は、ソースプログラムにおける先頭の関数に対応する命令列に着目して、次の手順を実行する。
【０１１５】
（Ｓ１７）タスク範囲抽出部１４２は、着目する命令列においてタスクの開始・終了位置を抽出し、スレッド数指定命令の直前にラベルを挿入する。例えば、ソースファイル１１１のコンパイルの場合、タスク範囲抽出部１４２は、タスクＡに対するラベルとして“．ｇｌｏｂａｌ  ｔａｓｋ  ００１”をオブジェクトファイル１２１向けの命令列に挿入する。タスク範囲抽出部１４２は、タスクＢに対するラベルとして“．ｇｌｏｂａｌ  ｔａｓｋ  ００２”をオブジェクトファイル１２１向けの命令列に挿入する。なお、タスク範囲抽出部１４２は、タスク範囲を抽出しないこともある。その場合は、ラベルの挿入も行われない。タスク範囲抽出部１４２は、タスク範囲情報として挿入したラベルのラベル名をＲＡＭ１０３に格納する。挿入したラベルがない場合は、ラベル名がなしである旨をタスク範囲情報とする。
【０１１６】
（Ｓ１８）関数コスト解析部１４３は、サイクル数テーブル１２５に基づいて、タスクおよび関数について呼び出し先の関数のコストを含まないコストＣ（ｔ，ｎ）を抽出し、タスクおよび関数毎の関数コスト情報を生成する。関数コスト解析部１４３は、生成した関数コスト情報をＲＡＭ１０３に格納する。
【０１１７】
（Ｓ１９）関数呼び出し抽出部１４４は、ソースプログラムに基づいて、関数の呼び出し関係を抽出し、タスクおよび関数毎の関数呼び出し情報を生成する。関数の呼び出しがない場合、関数呼び出しなしである旨を関数呼び出し情報として生成する。関数呼び出し抽出部１４４は、生成した関数呼び出し情報をＲＡＭ１０３に格納する。
【０１１８】
（Ｓ２０）タスク範囲抽出部１４２は、ソースプログラム中にステップＳ１７〜Ｓ１９の手順を未処理の関数があるか否かを判定する。未処理の関数がある場合、処理をステップＳ２１に進める。未処理の関数がない場合、処理をステップＳ２２に進める。
【０１１９】
（Ｓ２１）タスク範囲抽出部１４２は、処理対象を次の関数に進める（着目する関数が次の関数となる）。そして、処理をステップＳ１７に進める。
（Ｓ２２）関数情報追加部１４５は、ステップＳ１７，Ｓ１８，Ｓ１９で生成されたタスク範囲情報、関数コスト情報および関数呼び出し情報を、ＲＡＭ１０３から読み出して、オブジェクトファイルの生成時に、オブジェクトファイルに埋め込む。
【０１２０】
このようにして、コンパイラ１４０は、生成したオブジェクトファイルにタスク範囲情報、関数コスト情報および関数呼び出し情報を追加する。なお、コンパイラ１４０は、複数のソースファイルをコンパイルする際、上記ステップＳ１１〜Ｓ２２の一連の手順をソースファイル毎に繰り返し実行する。リンカ１５０は、コンパイラ１４０によって生成された上記オブジェクトファイルに基づいて、リンク処理を実行する。
【０１２１】
図２１は、リンク処理の例を示すフローチャートである。以下、図２１に示す処理をステップ番号に沿って説明する。
（Ｓ３１）関数情報取得部１５１は、結合対象の全てのオブジェクトファイル（例えば、オブジェクトファイル１２１，１２２，１２３，１２４）から、コンパイル時に埋め込まれた関数情報を取得する。関数情報は、タスク範囲情報、関数コスト情報および関数呼び出し情報を含む。
【０１２２】
（Ｓ３２）タスク範囲解析部１５２は、ステップＳ３１で取得されたタスク範囲情報からタスクのラベル名を取得する（ラベル名を取得できる場合は、並列に実行可能な複数のタスクに対応する複数のラベル名を取得することになる）。なお、各オブジェクトファイル内に並列タスクが存在しない場合、タスク範囲解析部１５２は、ラベル名を取得しないことになる。
【０１２３】
（Ｓ３３）タスク範囲解析部１５２は、並列タスクがあるか否かを判定する。並列タスクがある場合、処理をステップＳ３４に進める。並列タスクがない場合、処理をステップＳ３８に進める。例えば、ステップＳ３２でラベル名を取得できている場合、並列タスクがあることになる。一方、ステップＳ３２でラベル名を取得できていない場合、並列タスクがないことになる。
【０１２４】
（Ｓ３４）関数呼び出し解析部１５３は、ステップＳ３１で取得された関数呼び出し情報に基づいて、関数呼び出し関係を構築する。具体的には、関数呼び出し解析部１５３は、図１６で例示したように、あるタスクから関数を呼び出す呼び出し関係、および、ある関数から他の関数を呼び出す呼び出し関係を構築する。
【０１２５】
（Ｓ３５）タスクコスト解析部１５４は、ステップＳ３４で構築された関数呼び出し関係に基づいて、呼び出し先の関数も含めたタスク全体のコスト（スレッド数を示すパラメータを含むコスト）を見積もる。例えば、タスクＡに対してＡｌｌＣ（タスクＡ，ｎ）を見積もる。また、タスクＢに対してＡｌｌＣ（タスクＢ，ｍ）を見積もる。具体的な計算方法は、図１７で例示した通りである。例えば、タスクコスト解析部１５４は、見積もり結果を、タスクコストテーブル１３２に登録する。
【０１２６】
（Ｓ３６）スレッド数判定部１５５は、タスク毎のスレッド数を決定する（詳細は後述される）。
（Ｓ３７）スレッド数変更部１５６は、ステップＳ３６で決定されたタスク毎のスレッド数を、オブジェクトファイルに埋め込む。オブジェクトファイルにスレッド数を埋め込む方法は、図１９で例示した通りである。上記のオブジェクトファイル１２１，１２２，１２３，１２４に対する処理の場合、スレッド数変更部１５６は、これらのうちオブジェクトファイル１２１にスレッド数を埋め込むことになる。
【０１２７】
（Ｓ３８）リンカ１５０は、オブジェクトファイル１２１，１２２，１２３，１２４を用いて、実行可能ファイル１３１を生成し、実行可能ファイル記憶部１３０に格納する。ここで、ステップＳ３７を実行している場合、オブジェクトファイル１２１には、タスク毎のスレッド数が埋め込まれており、当該スレッド数の変更結果が実行可能ファイル１３１に反映されることになる。
【０１２８】
図２２は、スレッド数決定処理の例を示すフローチャートである。以下、図２２に示す処理をステップ番号に沿って説明する。以下の手順は、図２１のステップＳ３６に相当する。
【０１２９】
（Ｓ４１）スレッド数判定部１５５は、各タスクに割り当てるスレッド数を１にする。
（Ｓ４２）スレッド数判定部１５５は、各タスクに割り当てているスレッド数の和（スレッド総数）が利用可能なコア数よりも小さいか（スレッド総数＜コア数）否かを判定する。スレッド総数がコア数よりも小さい場合、処理をステップＳ４３に進める。スレッド総数がコア数よりも小さい場合、各タスクに現在割り当てているスレッド数を各タスクへ割り当てるスレッド数として確定し、処理を終了する。
【０１３０】
（Ｓ４３）スレッド数判定部１５５は、各タスクに現在割り当てているスレッド数を用いて各タスクの総コストを求める。例えば、タスクＡの総コストを求める場合、スレッド数判定部１５５は、現在のスレッド数をｎに代入してＡｌｌＣ（タスクＡ，ｎ）の値を求める。また、タスクＢの総コストを求める場合、スレッド数判定部１５５は、現在のスレッド数をｍに代入してＡｌｌＣ（タスクＢ，ｍ）の値を求める。
【０１３１】
（Ｓ４４）スレッド数判定部１５５は、最も総コストの高いタスクのスレッド数を１増やす。そして、処理をステップＳ４２に進める。
このようにして、スレッド数判定部１５５は、各タスクに対して割り当てるスレッド数を決定する。これにより、並列実行される各タスクの終了時刻の時間差を小さくすることができる。
【０１３２】
図２３は、ソースプログラムの他の例を示す図である。
第２の実施の形態では、並列タスクの数が２の場合を例示したが、並列タスクの数は３以上でもよい。例えば、図２３では、割り当てスレッド数として、それぞれ６，４，２が指定された３つの並列タスク（図中“＜タスク１＞”、“＜タスク２＞”、“＜タスク３＞”と表記）を定義する場合を示している。
【０１３３】
図２４は、タスクと関数との入れ子構造の例を示す図である。
更に、第２の実施の形態では、各タスクが関数呼び出し命令を含む場合を例示したが、一部のタスクが関数呼び出し命令を含まないこともある。例えば、図２４に示すように、並列実行可能な２つのタスクのうち、一方のタスクは、関数呼び出しを含む。もう一方のタスクは、ループ処理の記述を含むが、関数呼び出しを含まない。この場合、後者のタスク（関数呼び出しを含まないタスク）については、ＡｌｌＣ（ｔ，ｎ）＝Ｃ（ｔ，ｎ）となる。このように、並列タスクに、関数呼び出し命令を含むタスク、および、関数呼び出し命令を含まないタスクが混在する場合にも、第２の実施の形態の方法を適用して各タスクのスレッド数を決定できる。
【０１３４】
以上で説明したように、コンパイラ１４０は、ソースファイル毎に、該当のソースファイル内で定義されている各タスクと各関数のサイクル数を、タスクまたは関数のコストとして個別に求める。また、コンパイラ１４０は、タスクと関数の呼び出し関係を求める。そして、コンパイラ１４０は、出力として、コストと呼び出し関係をオブジェクトファイルに埋め込む。リンカ１５０は、各オブジェクトファイルに含まれるコストと呼び出し関係を入力として受け取る。そして、リンカ１５０は、タスクと関数の呼び出し関係を構築し、タスクから呼び出される関数のコストを含めたタスク全体のコストを求める。
【０１３５】
これにより、複数のソースファイルに跨ったタスクでも、タスク全体のコストを求めることができる。そして、求めたタスク全体のコストに応じて、並列に実行される各タスクの処理終了時刻ができる限り同じになるよう、各タスクへのスレッド数を調整できる。このため、コストを考慮せずにタスクへのスレッド数を割り当てるよりも、適切なスレッド数で各タスクを実行でき、全体の実行を短縮することができる。
【０１３６】
コンパイラ１４０は、関数コスト情報や関数の呼び出し関係を、各オブジェクトファイルに埋め込むので、関数コスト情報や関数の呼び出し関係を別個のファイルで管理しなくてよい。リンカ１５０は、結合対象の各オブジェクトファイルを参照することで、関数コスト情報や関数の呼び出し関係の情報を取得することができる。
【０１３７】
また、各タスクのコストを把握するために、実行可能ファイルを実行して各タスクのコストを測定しなくてもよい。更に、タスク全体を解析するために要するメモリ量は、ソースプログラム全体よりも少ない。そのため、ソースプログラムを一度にまとめて（例えば、１つのソースファイルにまとめて）解析するよりも、メモリ使用量が少なくて済む。
【０１３８】
なお、第１の実施の形態の情報処理は、計算機１にプログラムを実行させることで実現できる。また、第２の実施の形態の情報処理は、情報処理装置１００にプログラムを実行させることで実現できる。
【０１３９】
プログラムは、コンピュータ読み取り可能な記録媒体１３に記録できる。例えば、プログラムを記録した記録媒体１３を配布することで、プログラムを流通させることができる。また、プログラムを他のコンピュータに格納しておき、ネットワーク経由でプログラムを配布してもよい。コンピュータは、例えば、記録媒体１３に記録されたプログラムまたは他のコンピュータから受信したプログラムを、ＲＡＭ１０３やＨＤＤ１０４などの記憶装置に格納し（インストールし）、当該記憶装置からプログラムを読み込んで実行してもよい。
【０１４０】
以上の第１，第２の実施の形態を含む実施形態に関し、更に以下の付記を開示する。
（付記１）  ソースプログラムを記憶する記憶部と、
前記ソースプログラムのコンパイルの際に、前記ソースプログラムに含まれる関数毎の実行に要するサイクル数とタスクおよび関数の呼び出し関係とを示す情報を生成し、
リンク処理の際に、前記サイクル数および前記呼び出し関係に基づいてタスク毎の実行に要するサイクル数を算出する演算部、
を有するコンパイルを行う計算機。
【０１４１】
（付記２）  前記演算部は、前記コンパイル時に生成された前記サイクル数および前記呼び出し関係の情報を前記コンパイルにより生成されたオブジェクトファイルに追加する、付記１記載の計算機。
【０１４２】
（付記３）  前記演算部は、前記リンク処理の際に、結合対象の複数のオブジェクトファイルから前記コンパイル時に生成された前記サイクル数および前記呼び出し関係を取得する、付記１または２記載の計算機。
【０１４３】
（付記４）  前記タスクおよび前記タスクから呼び出される前記関数は、異なるソースファイルに定義されている、付記１乃至３の何れか１つに記載の計算機。
（付記５）  前記コンパイル時に生成される前記サイクル数の情報は、前記タスクの定義に含まれる命令の実行に要するサイクル数を含む、付記１乃至４の何れか１つに記載の計算機。
【０１４４】
（付記６）  前記記憶部は、命令とサイクル数との対応関係の情報を記憶し、
前記演算部は、前記コンパイルの際に、前記ソースプログラムから生成された命令列と前記対応関係に基づいて、前記サイクル数の情報を生成する、
付記１乃至５の何れか１つに記載の計算機。
【０１４５】
（付記７）  前記演算部は、前記リンク処理の際に、前記呼び出し関係に基づいて前記タスクから呼び出される第１の関数および前記第１の関数から呼び出される第２の関数を特定し、前記第１の関数および前記第２の関数それぞれに関するサイクル数の和に基づいて前記タスクの実行に要するサイクル数を算出する、付記１乃至６の何れか１つに記載の計算機。
【０１４６】
（付記８）  前記演算部は、前記リンク処理の際に、並列に実行可能な複数のタスクそれぞれのサイクル数に基づいて、前記複数のタスクそれぞれに割り当てるスレッド数を決定する、付記１乃至７の何れか１つに記載の計算機。
【０１４７】
（付記９）  前記演算部は、前記複数のタスクそれぞれに割り当てるスレッド数の組み合わせの候補毎に前記複数のタスクそれぞれのサイクル数を算出し、前記複数のタスクそれぞれのサイクル数の差が最小になるスレッド数の組み合わせを選択する、付記８記載の計算機。
【０１４８】
（付記１０）  前記演算部は、決定したスレッド数の情報を前記コンパイルにより生成されたオブジェクトファイルに追加し、当該オブジェクトファイルを用いて実行可能ファイルを生成する、付記８または９記載の計算機。
【０１４９】
（付記１１）  コンピュータに、
ソースプログラムのコンパイルの際に、前記ソースプログラムに含まれる関数毎の実行に要するサイクル数とタスクおよび関数の呼び出し関係とを示す情報を出力する、
処理を実行させるコンパイラプログラム。
【０１５０】
（付記１２）  コンピュータに、
ソースプログラムのコンパイルの際に生成された、前記ソースプログラムに含まれる関数毎の実行に要するサイクル数とタスクおよび関数の呼び出し関係とを示す情報に基づいて、タスク毎の実行に要するサイクル数を算出する、
処理を実行させるリンクプログラム。
【０１５１】
（付記１３）  コンピュータが、
ソースプログラムのコンパイルの際に、前記ソースプログラムに含まれる関数毎の実行に要するサイクル数とタスクおよび関数の呼び出し関係とを示す情報を生成し、
リンク処理の際に、前記サイクル数および前記呼び出し関係に基づいてタスク毎の実行に要するサイクル数を算出する、
コンパイル方法。
【符号の説明】
【０１５２】
１  計算機
１ａ  記憶部
１ｂ  演算部
２  コンパイラ
３  リンカ
４  第１のソースプログラム
４ａ  第１のオブジェクトファイル
５  第２のソースプログラム
５ａ  第２のオブジェクトファイル
【図１】
0006500626.tif 000002
【図２】
0006500626.tif 000003
【図３】
0006500626.tif 000004
【図４】
0006500626.tif 000005
【図５】
0006500626.tif 000006
【図６】
0006500626.tif 000007
【図７】
0006500626.tif 000008
【図８】
0006500626.tif 000009
【図９】
0006500626.tif 000010
【図１０】
0006500626.tif 000011
【図１１】
0006500626.tif 000012
【図１２】
0006500626.tif 000013
【図１３】
0006500626.tif 000014
【図１４】
0006500626.tif 000015
【図１５】
0006500626.tif 000016
【図１６】
0006500626.tif 000017
【図１７】
0006500626.tif 000018
【図１８】
0006500626.tif 000019
【図１９】
0006500626.tif 000020
【図２０】
0006500626.tif 000021
【図２１】
0006500626.tif 000022
【図２２】
0006500626.tif 000023
【図２３】
0006500626.tif 000024
【図２４】
0006500626.tif 000025