(57)【特許請求の範囲】
【請求項１】
先行タスク、後続タスク、タスク間に生じる直接および間接の先行関係タイプを格納する閉包先行関係記憶手段と、先行タスク、後続タスク、タスク間に生じる直接の先行関係タイプを格納する縮退先行関係記憶手段と、タスク間の先行後続関係に基づくスケジューリングを実現するために用いる同期機構イベントの識別子と先行、後続として配置できなかったタスク間の先行関係とを格納するイベント記憶手段と、スケジュールの結果を記憶するタスク配置記憶手段とを備えたシステムにおいて実行される方法であって、
前記システムの先行関係管理手段が、スケジュール作成対象のプログラムのタスク間の先行関係データを受信するステップと、
前記先行関係管理手段が、前記先行関係データに含まれる先行関係から、間接的な先行関係を識別し、前記識別された間接的な先行関係を取り除いた先行関係タイプを前記縮退先行関係記憶手段に記憶させるとともに、前記閉包先行関係記憶手段の先行関係タイプを直接、間接を区別して記憶させるステップと、
前記システムのタスク配置手段が、前記縮退先行関係記憶手段に記録された先行関係に対し、ＰＥＲＴ解析を使用して、各タスクの実行時間を１とした場合の各タスクの開始時間を算出するステップと、
前記タスク配置手段が、前記算出した開始時間に基づいて、前記各タスクの開始時間に対応する１以上のレイヤ、およびスケジュール作成対象のプログラムの実行のフィニッシュ時間に対応するレイヤを有するタスク配置構造体を生成するステップと、
前記タスク配置手段が、レイヤ１をレイヤ１内に存在するタスク数のレベルで分割し、
分割した領域にタスクを配置するステップと、
前記タスク配置手段が、処理対象のレイヤを示すレイヤＬに、レイヤ２をセットするステップと、
前記タスク配置手段が、前記レイヤＬが前記フィニッシュ時間に対応するレイヤｔであるか否か判定するステップであって、レイヤｔである場合、前記タスク配置構造体および前記イベント記憶手段に基づいて、スケジュールを作成し、レイヤｔでない場合、
前記タスク配置手段が、前記レイヤＬおよび前記レイヤＬの１つ前のレイヤであるレイヤ内のタスク数を比較して、いずれか一方のレイヤ内のタスク数が他方のレイヤ内のタスク数より少ない場合、空タスクを生成して両レイヤ内のタスク数を同一にするステップと、
前記タスク配置手段が、前記閉包先行関係記憶手段に基づいて、前記レイヤＬの１つ前のレイヤであるレイヤ内の各タスクに対して、後続となり得る前記レイヤＬ内のタスク（後続タスク候補）の集合を判定するステップと、
前記タスク配置手段が、グラフの最大マッチングアルゴリズムを用いて、前記レイヤＬの１つ前のレイヤであるレイヤ内の各タスクとその後続タスクについて、最大マッチングを取得するステップと、
前記タスク配置手段が、前記最大マッチングのマッチング数が前記レイヤＬの１つ前のレイヤであるレイヤ内のタスク数より少ない場合、最大マッチングのマッチング数が前記レイヤＬの１つ前のレイヤであるレイヤ内のタスク数と一致するまで、マッチング数とタスク数の差の数、前記レイヤＬおよび前記レイヤＬの１つ前のレイヤであるレイヤに空タスクを生成し、空タスクを配置するために新たなレベルの領域を作成し、前記後続タスク候補の集合を判定するステップ、および前記最大マッチングを取得するステップを繰り返す、ステップと、
前記タスク配置手段が、前記レイヤＬのレイヤを当該レイヤ内に存在するタスク数のレベルで分割し、前記レイヤＬの１つ前のレイヤであるレイヤ内の各タスクとその後続タスクとが、同一レベルになるように分割した領域にタスクを配置するステップと、
前記システムのイベント識別手段が、前記レイヤＬの１つ前のレイヤであるレイヤ内のタスクｘの後続として前記レイヤＬ内に配置できなかったタスクｙを識別し、先行、後続として配置できなかったタスク間の先行関係を、前記同期機構イベントを使って表現するため、前記タスクxと前記タスクyとイベント識別子を前記イベント記憶手段に記憶するステップと、
前記タスク配置手段が、前記レイヤＬに１を加算することにより現在処理中のレイヤの次のレイヤを処理対象のレイヤとしてセットするステップを行い、
前記レイヤＬが前記フィニッシュ時間に対応するレイヤｔであるか否か判定するステップに戻す、ステップと
を含むことを特徴とする方法。
【請求項２】
前記タスク配置構造体および前記イベント記憶手段に基づいて、スケジュールを作成するステップは、
前記システムのスケジュール変換手段が、前記タスク配置構造体にスケジュール未作成のレベルが存在するか否か判定し、存在する場合に、後続の処理を続けるステップと、
前記スケジュール変換手段が、前記タスク配置構造体のレベルのうち、スケジュールを作成していないレベルを抽出し、かつ、処理対象のレイヤを示すレイヤＣに、１をセットするステップと、
前記スケジュール変換手段が、前記レイヤＣが前記レイヤｔであるか否か判定するステップであって、レイヤｔである場合、前記タスク配置構造体にスケジュール未作成のレベルが存在するか否か判定するステップに戻り、レイヤｔでない場合、
前記スケジュール変換手段が、前記レイヤＣに配置されたタスクを識別するステップと、
前記スケジュール変換手段が、前記イベント記憶手段に基づいて、前記識別したタスクを実行する前に待機すべきイベントが存在するか否かを判定し、存在する場合に、イベントを待機するために待機タスクをスケジュールに挿入するステップと、
前記スケジュール変換手段が、前記識別したタスクが空タスクでない場合、当該タスクの実行をスケジュールとして記述するステップと、
前記スケジュール変換手段が、前記イベント記憶手段に基づいて、前記識別したタスクの完了を通知すべきイベントが存在するか否かを判定し、存在する場合に、イベントを通知する通知タスクをスケジュールに挿入するステップと、
前記スケジュール変換手段が、前記レイヤＣに１を加算し現在処理中のレイヤの次のレイヤをセットするステップを行い、
前記レイヤＣが前記レイヤｔであるか否か判定するステップに戻すステップと
を含むことを特徴とする請求項１に記載の方法。
【請求項３】
前記先行関係データはＰＥＲＴ図であり、
前記先行関係管理手段が、前記先行関係データからタスクに対応するノードの集合、およびタスク間の先行関係を表す矢印の集合を抽出するステップと、
前記先行関係管理手段が、タスク間に生じる間接の先行関係を識別するステップと
をさらに含むことを特徴とする請求項１または２に記載の方法。
【請求項４】
前記先行関係管理手段は、直接の先行関係および間接の先行関係を有する場合には、前記閉包先行関係記憶手段に間接の先行関係を優先して登録することを特徴とする請求項１乃至３のいずれかに記載の方法。
【請求項５】
前記スケジュール変換手段は、同期プリミティブを用いて前記待機すべきイベントおよび前記通知すべきイベントを記述することを特徴とする請求項２に記載の方法。
【請求項６】
前記タスク配置構造体を、前記システムのタスク配置記憶手段に記憶するステップをさらに含むことを特徴とする請求項１乃至５のいずれかに記載の方法。
【請求項７】
先行タスク、後続タスク、タスク間に生じる直接および間接の先行関係タイプを格納する閉包先行関係記憶手段と、先行タスク、後続タスク、タスク間に生じる直接の先行関係タイプを格納する縮退先行関係記憶手段と、
タスク間の先行後続関係に基づくスケジューリングを実現するために用いる同期機構イベントの識別子と先行、後続として配置できなかったタスク間の先行関係とを格納するイベント記憶手段と、
スケジュールの結果を記憶するタスク配置記憶手段と、
スケジュール作成対象のプログラムのタスク間の先行関係データを受信し、前記先行関係データに含まれる先行関係から、間接的な先行関係を識別し、前記識別された間接的な先行関係を取り除いた先行関係タイプを前記縮退先行関係記憶手段に記憶させるとともに、前記閉包先行関係記憶手段の先行関係タイプを直接、間接を区別して記憶させる先行関係管理手段と、
前記縮退先行関係記憶手段に記録された先行関係に対し、ＰＥＲＴ解析を使用して、各タスクの実行時間を１とした場合の各タスクの開始時間を算出し、前記算出した開始時間に基づいて、前記各タスクの開始時間に対応する１以上のレイヤ、およびスケジュール作成対象のプログラムの実行のフィニッシュ時間に対応するレイヤを有するタスク配置構造体を生成し、レイヤ１をレイヤ１内に存在するタスク数のレベルで分割して、分割した領域にタスクを配置し、処理対象のレイヤを示すレイヤＬにレイヤ２をセットし、前記レイヤＬが前記フィニッシュ時間に対応するレイヤｔであるか否か判定し、レイヤｔでない場合、ステップ（１）から（６）を繰り返すタスク配置手段であって、
（１）前記レイヤＬおよび前記レイヤＬの１つ前のレイヤであるレイヤ内のタスク数を比較して、いずれか一方のレイヤ内のタスク数が他方のレイヤ内のタスク数より少ない場合、空タスクを生成して両レイヤ内のタスク数を同一にし、
（２）前記閉包先行関係記憶手段に基づいて、前記レイヤＬの１つ前のレイヤであるレイヤ内の各タスクに対して、後続となり得る前記レイヤＬ内のタスク（後続タスク候補）の集合を判定し、
（３）グラフの最大マッチングアルゴリズムを用いて、前記レイヤＬの１つ前のレイヤであるレイヤ内の各タスクとその後続タスクについて、最大マッチングを取得し、
（４）前記最大マッチングのマッチング数が前記レイヤＬの１つ前のレイヤであるレイヤ内のタスク数より少ない場合、最大マッチングのマッチング数が前記レイヤＬの１つ前のレイヤであるレイヤ内のタスク数と一致するまで、マッチング数とタスク数の差の数、前記レイヤＬおよび前記レイヤＬの１つ前のレイヤであるレイヤに空タスクを生成し、空タスクを配置するために新たなレベルの領域を作成し、（２）および（３）を繰り返し、
（５）前記レイヤＬのレイヤを当該レイヤ内に存在するタスク数のレベルで分割し、前記レイヤＬの１つ前のレイヤであるレイヤ内の各タスクとその後続タスクとが、同一レベルになるように分割した領域にタスクを配置し、
（６）前記レイヤＬに１を加算することにより現在処理中のレイヤの次のレイヤをセットし、前記レイヤＬがフィニッシュ時間に対応するレイヤｔでない場合、（１）に戻す
タスク配置手段と、
前記レイヤＬの１つ前のレイヤであるレイヤ内のタスクｘの後続として前記レイヤＬ内に配置できなかったタスクｙを識別し、先行、後続として配置できなかったタスク間の先行関係を、前記同期機構イベントを使って表現するため、前記タスクxと前記タスクyとイベント識別子を前記イベント記憶手段に記憶するイベント識別手段と、 
前記タスク配置構造体および前記イベント記憶手段に基づいて、スケジュールを作成するスケジュール変換手段と
を備えたことを特徴とするシステム。
【請求項８】
先行タスク、後続タスク、タスク間に生じる直接および間接の先行関係タイプを格納する閉包先行関係記憶手段と、先行タスク、後続タスク、タスク間に生じる直接の先行関係タイプを格納する縮退先行関係記憶手段と、タスク間の先行後続関係に基づくスケジューリングを実現するために用いる同期機構イベントの識別子と先行、後続として配置できなかったタスク間の先行関係とを格納するイベント記憶手段とスケジュールの結果を記憶するタスク配置記憶手段とを備えたシステムに、タスク間の先行関係に基づいてスケジュールを作成させるためのプログラムであって、
前記システムの先行関係管理手段が、スケジュール作成対象のプログラムのタスク間の先行関係データを受信するステップと、
前記先行関係管理手段が、前記先行関係データに含まれる先行関係から、間接的な先行関係を識別し、前記識別された間接的な先行関係を取り除いた先行関係タイプを前記縮退先行関係記憶手段に記憶させるとともに、前記閉包先行関係記憶手段の先行関係タイプを直接、間接を区別して記憶させるステップと、
前記システムのタスク配置手段が、前記縮退先行関係記憶手段に記録された先行関係に対し、ＰＥＲＴ解析を使用して、各タスクの実行時間を１とした場合の各タスクの開始時間を算出するステップと、
前記タスク配置手段が、前記算出した開始時間に基づいて、前記各タスクの開始時間に対応する１以上のレイヤ、およびスケジュール作成対象のプログラムの実行のフィニッシュ時間に対応するレイヤを有するタスク配置構造体を生成するステップと、
前記タスク配置手段が、レイヤ１をレイヤ１内に存在するタスク数のレベルで分割し、分割した領域にタスクを配置するステップと、
前記タスク配置手段が、処理対象のレイヤを示すレイヤＬにレイヤ２をセットするステップと、
前記タスク配置手段が、前記レイヤＬが前記フィニッシュ時間に対応するレイヤｔであるか否か判定するステップであって、レイヤｔである場合、前記タスク配置構造体および前記イベント記憶手段に基づいて、スケジュールを作成し、レイヤｔでない場合、
前記タスク配置手段が、前記レイヤＬおよび前記レイヤＬの１つ前のレイヤであるレイヤ内のタスク数を比較して、いずれか一方のレイヤ内のタスク数が他方のレイヤ内のタスク数より少ない場合、空タスクを生成して両レイヤ内のタスク数を同一にするステップと、
前記タスク配置手段が、前記閉包先行関係記憶手段に基づいて、前記レイヤＬの１つ前のレイヤであるレイヤ内の各タスクに対して、後続となり得る前記レイヤＬ内のタスク（後続タスク候補）の集合を判定するステップと、
前記タスク配置手段が、グラフの最大マッチングアルゴリズムを用いて、前記レイヤＬの１つ前のレイヤであるレイヤ内の各タスクとその後続タスクについて、最大マッチングを取得するステップと、
前記タスク配置手段が、前記最大マッチングのマッチング数が前記レイヤＬの１つ前のレイヤであるレイヤ内のタスク数より少ない場合、最大マッチングのマッチング数が前記レイヤＬの１つ前のレイヤであるレイヤ内のタスク数と一致するまで、マッチング数とタスク数の差の数、前記レイヤＬおよび前記レイヤＬの１つ前のレイヤであるレイヤに空タスクを生成し、空タスクを配置するために新たなレベルの領域を作成し、前記後続タスク候補の集合を判定するステップ、および前記最大マッチングを取得するステップを繰り返す、ステップと、
前記タスク配置手段が、前記レイヤＬのレイヤを当該レイヤ内に存在するタスク数のレベルで分割し、前記レイヤＬの１つ前のレイヤであるレイヤ内の各タスクとその後続タスクとが、同一レベルになるように分割した領域にタスクを配置するステップと、
前記システムのイベント識別手段が、前記レイヤＬの１つ前のレイヤであるレイヤ内のタスクｘの後続として前記レイヤＬ内に配置できなかったタスクｙを識別し、先行、後続として配置できなかったタスク間の先行関係を、前記同期機構イベントを使って表現するため、前記タスクxと前記タスクyとイベント識別子を前記イベント記憶手段に記憶するステップと、
前記タスク配置手段が、前記レイヤＬに１を加算することにより現在処理中のレイヤの次のレイヤを処理対象のレイヤとしてセットするステップを行い、
前記レイヤＬがフィニッシュ時間に対応するレイヤｔであるか否か判定するステップに戻す、ステップと
を含むことを特徴とするプログラム。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、スケジュール作成方法、そのシステムおよびプログラムに関し、より詳細には、実行時間が特定されない複数のタスクを、そのタスク間の先行関係のみに基づいてスケジューリングする方法、そのシステムおよびプログラムに関する。
【背景技術】
【０００２】
クラウドコンピューティングは次世代のコンピューティング環境として期待を集めている。クラウドサービスを利用すると、システムの実行環境（サーバ、ストレージ、ネットワークなど）の調達・増強・縮退が短時間で可能であり、使った時間だけ利用料を払えばよい。従来、ソフトウェアシステムは、運用時にはごく稀にしか起きないピーク性能を基準に実行環境をサイジングし、その固定的な実行環境を前提に構築されてきた。その結果、低い平均負荷、高い運用コストを招いていた。クラウドでは、必要に応じて実行環境のサイズを変えられるので、運用コストの削減が期待できる。
【０００３】
図１に、クラウドコンピューティングの概略図を示す。複数のサーバ１０１ａ、１０１ｂ、・・・、１０１ｎ（以下、サーバ１０１と呼ぶ）が、インターネット１０２を介して、複数のクライアントコンピュータ１０３ａ、１０３ｂ、・・・、１０３ｎ（以下、クライアントコンピュータ１０３と呼ぶ）と相互に通信可能に接続される。
【０００４】
サーバ１０１は、利用者に提供するサービスを実現するためのプログラムを格納するメモリを有し、利用者の要求に応答して、ストレージに格納されたプログラムを処理するために必要なデータを用いて、サービスを提供する。
【０００５】
クライアントコンピュータ１０３は、クラウドサービスの利用者によって使用される端末である。利用者は、クライアントコンピュータ１０３を介して、サーバ１０１が提供するサービスを、サーバ群を意識することなしに利用する。
【０００６】
また、従来、ソフトウェアシステムの開発段階において、マシンリソースの不足が開発スケジュール遅延の原因となることが多かった。例えば、試験工程では、マシンリソースの不足により、多くの期間を費やすこととなる。開発段階においてクラウドコンピューティングを利用することで、マシンリソースに制約されない開発が可能になり、開発期間の短縮、開発費の削減が期待できる。このようにクラウドコンピューティングは、従来のソフトウェアシステムの諸問題を解決できる可能性を秘めている。
【０００７】
クラウドコンピューティングには課題もある。一般に、ソフトウェアシステムは、機能要求に加えて、性能要求も満たす必要がある。従来、固定された実行環境において性能試験を行うことにより、一定の性能を保証してきた。従来型システムでは、実際に運用される実行環境が固定されるので、同実行環境における試験結果が、運用時に成り立つと類推可能だからである。一方、クラウドサービスでは、ベストエフォートで実行環境を提供する。
【０００８】
ベストエフォート型では、例えば、ＣＰＵのクロック数に関して、あるユーザーがＣＰＵ負荷の高いプログラムを実行すると、同一環境を利用する別のユーザーの性能は劣化する。また、ストレージに関して、あるユーザーがストレージに過剰な負荷をかける大量のトランザクションを処理すると、同様に、同一環境を利用する別のユーザーのＩ／Ｏ性能は劣化する。ネットワークに関しても同様である。これでは、実行環境を特定することができず、従って、性能試験の結果が運用時にも成り立つとの類推はできない。
【０００９】
このような問題を解決するため、本件出願人は、実行環境を固定できないクラウドコンピューティングにおいて、システムとしての性能（スループット）を保証する手段を提供することに成功した。システムとしての性能を保証するために、当該技術では、タイマーにより、定められた一定の処理を実行し、それが終了すると、次にタイマーにより駆動されるまで休むよう動作するクロック駆動プログラミング（ＣＤＰ）のプログラムを処理する。高速マシンを使うと、実行時間は減少するが、その分休止時間が増える。低速マシンを使うと、実行時間が増加し、その分休止時間が減少する。すなわち、高速マシンおよび低速マシンのいずれを用いても、時間当たりの実行ステップ数は同じになる。従って、性能（スループット）はハードウェアには依存せずに同一になる。
【００１０】
ただし、周期Ｔを保ってプログラムを実行するために、以下の式で示されるデューティ率（Ｄ）は１未満である必要がある。τは実行時間である。
【００１１】
【数１】
0005486034.tif 000002
【発明の概要】
【発明が解決しようとする課題】
【００１２】
複数のタスクをどの時刻でどのＣＰＵにより実行するかを決定する従来のスケジューリング方法では、タスク間の先行関係、各タスクの実行時間、リソース数（ＣＰＵ数）を特定し、リソース数の制約のもとで実行時間が最小となるスケジュールを作成することを目的としていた。
【００１３】
この方法では、まず第１に、タスクの実行時間が変わるたびに、スケジュールを再作成する必要があった。タスクの実行時間は、ＣＰＵのスペック（アーキテクチャ、クロック周波数、キャッシュサイズなど）に応じて変化する。今日、ＣＰＵのスペックは多種多様である。そのため、ＣＰＵのスペック毎に対応するスケジュールを作成する従来の方法では、多種多様なＣＰＵをサポートすることは困難である。
【００１４】
また、第２に、リソース数に制約を設けることに疑問がもたれる。今日一般的に普及しているマルチコア環境では、ＣＰＵ数を自由に増やすことができる。例えば、デスクトップコンピュータでは６コアや８コア、サーバコンピュータでは数十コアを容易に搭載し得る。このような技術進歩を考慮すると、もはや、リソース数は決定的な制約とはなりえない。
【００１５】
さらに、第３に、実行時間が特定されない場合には、利用することができない。前述のＣＤＰは、特に、実行環境を固定できないクラウドコンピューティングにおいて効果を発揮する。しかし、ＣＰＵの性能など、クラウドコンピューティングの実行環境により実行時間が変わるので、実行時間を特定することはできない。
【００１６】
本発明は、このような問題に鑑みてなされたもので、その目的とするところは、実行時間が特定されない複数のタスクを、そのタスク間の先行関係のみに基づいてスケジューリングする手段を提供することにある。
【課題を解決するための手段】
【００１７】
上記の課題を解決するために、本発明に係るスケジュール作成方法は、先行タスク、後続タスク、タスク間に生じる直接および間接の先行関係タイプを格納する閉包先行関係記憶手段と、先行タスク、後続タスク、タスク間に生じる直接の先行関係タイプを格納する縮退先行関係記憶手段と、タスク間の先行後続関係に基づくスケジューリングを実現するために用いる同期機構イベントの識別子と先行、後続として配置できなかったタスク間の先行関係とを格納するイベント記憶手段と、スケジュールの結果を記憶するタスク配置記憶手段とを備えたシステムにおいて実行される方法であって、前記システムの先行関係管理手段が、スケジュール作成対象のプログラムのタスク間の先行関係データを受信するステップと、前記先行関係管理手段が、前記先行関係データに含まれる先行関係から、間接的な先行関係を識別し、前記識別された間接的な先行関係を取り除いた先行関係タイプを前記縮退先行関係記憶手段に記憶させるとともに、前記閉包先行関係記憶手段の先行関係タイプを直接、間接を区別して記憶させるステップと、前記システムのタスク配置手段が、前記縮退先行関係記憶手段に記録された先行関係に対し、ＰＥＲＴ解析を使用して、各タスクの実行時間を１とした場合の各タスクの開始時間を算出するステップと、前記タスク配置手段が、前記算出した開始時間に基づいて、前記各タスクの開始時間に対応する１以上のレイヤ、およびスケジュール作成対象のプログラムの実行のフィニッシュ時間に対応するレイヤを有するタスク配置構造体を生成するステップと、前記タスク配置手段が、レイヤ１をレイヤ１内に存在するタスク数のレベルで分割し、分割した領域にタスクを配置するステップと、前記タスク配置手段が、処理対象のレイヤを示すレイヤＬに、レイヤ２をセットするステップと、前記タスク配置手段が、前記レイヤＬが前記フィニッシュ時間に対応するレイヤｔであるか否か判定するステップであって、レイヤｔである場合、前記タスク配置構造体および前記イベント記憶手段に基づいて、スケジュールを作成し、レイヤｔでない場合、前記タスク配置手段が、前記レイヤＬおよび前記レイヤＬの１つ前のレイヤであるレイヤ内のタスク数を比較して、いずれか一方のレイヤ内のタスク数が他方のレイヤ内のタスク数より少ない場合、空タスクを生成して両レイヤ内のタスク数を同一にするステップと、前記タスク配置手段が、前記閉包先行関係記憶手段に基づいて、前記レイヤＬの１つ前のレイヤであるレイヤ内の各タスクに対して、後続となり得る前記レイヤＬ内のタスク（後続タスク候補）の集合を判定するステップと、前記タスク配置手段が、グラフの最大マッチングアルゴリズムを用いて、前記レイヤＬの１つ前のレイヤであるレイヤ内の各タスクとその後続タスクについて、最大マッチングを取得するステップと、
前記タスク配置手段が、前記最大マッチングのマッチング数が前記レイヤＬの１つ前のレイヤであるレイヤ内のタスク数より少ない場合、最大マッチングのマッチング数が前記レイヤＬの１つ前のレイヤであるレイヤ内のタスク数と一致するまで、マッチング数とタスク数の差の数、前記レイヤＬおよび前記レイヤＬの１つ前のレイヤであるレイヤに空タスクを生成し、空タスクを配置するために新たなレベルの領域を作成し、前記後続タスク候補の集合を判定するステップ、および前記最大マッチングを取得するステップを繰り返す、ステップと、前記タスク配置手段が、前記レイヤＬのレイヤを当該レイヤ内に存在するタスク数のレベルで分割し、前記レイヤＬの１つ前のレイヤであるレイヤ内の各タスクとその後続タスクとが、同一レベルになるように分割した領域にタスクを配置するステップと、前記システムのイベント識別手段が、前記レイヤＬの１つ前のレイヤであるレイヤ内のタスクｘの後続として前記レイヤＬ内に配置できなかったタスクｙを識別し、先行、後続として配置できなかったタスク間の先行関係を、前記同期機構イベントを使って表現するため、前記タスクxと前記タスクyとイベント識別子を前記イベント記憶手段に記憶するステップと、前記タスク配置手段が、前記レイヤＬに１を加算することにより現在処理中のレイヤの次のレイヤを処理対象のレイヤとしてセットするステップを行い、前記レイヤＬが前記フィニッシュ時間に対応するレイヤｔであるか否か判定するステップに戻す、ステップとを含むことを特徴とする。
【発明の効果】
【００１８】
本発明により、タスクの実行時間に依存しないスケジュールを作成することができる。そのため、タスクの実行時間が変わっても、スケジュールを再作成する必要はなくなる。また、得られるスケジュールは、いずれの実行環境においても、最小時間での実行を保障することができる。
【００１９】
さらに、本発明で導かれるスケジュールにより、最小時間で実行するための最少リソース数を得ることができる。最少リソース数を知ることにより、不必要なリソースを維持する不利益を回避することができる。
【図面の簡単な説明】
【００２０】
【図１】クラウドコンピューティングの概略図である。
【図２】本発明の一実施形態に係るタスクのプログラム記述例を示す図である。
【図３】本発明の一実施形態に係る別のタスクを利用するタスクのプログラム記述例を示す図である。
【図４】本発明の一実施形態に係るタスク配列のプログラム記述例を示す図である。
【図５】本発明の一実施形態に係るタスクのコールグラフを示す図である。
【図６】本発明の一実施形態に係るタスクのＰＥＲＴ図である。
【図７】本発明の一実施形態に係るタスクのコールグラフを示す図である。
【図８Ａ】ポーリングを用いたタスクのプログラム記述例を示す。
【図８Ｂ】ポーリングを用いたタスクのプログラム記述例を示す。
【図９】本発明の一実施形態に係るタスクのＰＥＲＴ図である。
【図１０】本発明の一実施形態に係るタスク間の先行関係を示す先行関係表である。
【図１１Ａ】変数リネーム技法を適用する前のプログラム記述例を示す図である。
【図１１Ｂ】変数リネーム技法を適用する後のプログラム記述例を示す図である。
【図１２】個別化技法を適用する前後のコールグラフを示す図である。
【図１３Ａ】抽選化技法を適用したタスクのプログラム記述例を示す図である。
【図１３Ｂ】抽選化技法を適用したタスクのプログラム記述例を示す図である。
【図１４】本発明の一実施形態に係るタスクのＰＥＲＴ図である。
【図１５】本発明の一実施形態に係るタスクを実行するプログラム記述例を示す図である。
【図１６】本発明の一実施形態に係るタスクを実行するプログラム記述例を示す図である。
【図１７】本発明の一実施形態に係るタスクを並列実行するシーケンス図である。
【図１８】本発明の一実施形態に係るスケジュール作成システムの構成を示すブロック図である。
【図１９】本発明の一実施形態に係る閉包先行関係記憶手段に格納された情報の一例を示す図である。
【図２０】本発明の一実施形態に係る縮退先行関係記憶手段に格納された情報の一例を示す図である。
【図２１】本発明の一実施形態に係るイベント記憶手段に格納された情報の一例を示す図である。
【図２２】本発明の一実施形態に係るスケジュールを作成する工程を示すフローチャートである。
【図２３】本発明の一実施形態に係るタスクのＰＥＲＴ図である。
【図２４】本発明の一実施形態に係るタスク構造体に配置されているＰＥＲＴ図のイメージ図である。
【図２５】本発明の一実施形態に係るタスク構造体に配置されているＰＥＲＴ図のイメージ図である。
【図２６】本発明の一実施形態に係るタスク構造体に配置されているＰＥＲＴ図のイメージ図である。
【図２７】本発明の一実施形態に係るタスク構造体に配置されているＰＥＲＴ図のイメージ図である。
【図２８】本発明の一実施形態に係るタスク構造体に配置されているＰＥＲＴ図のイメージ図である。
【図２９】本発明の一実施形態に係るタスク構造体に配置されているＰＥＲＴ図のイメージ図である。
【図３０】本発明の一実施形態に係るタスク構造体に配置されているＰＥＲＴ図のイメージ図である。
【図３１】本発明の一実施形態に係るタスク構造体に配置されているＰＥＲＴ図のイメージ図である。
【図３２】本発明の一実施形態に係るスケジュールを作成する工程を示すフローチャートである。
【発明を実施するための形態】
【００２１】
（ＣＤＰプログラム）
初めに、ＣＤＰプログラムについて説明する。ＣＤＰは、イベント駆動プログラミング（ＥＤＰ）の一部である。従って、ＣＤＰは、ＥＤＰをサポートする任意のプログラミング言語、およびＯＳで実践できる。本実施形態では、C言語、およびWindows（登録商標）を用いるが、これに限定されるものではない。
【００２２】
ＣＤＰとＥＤＰとの違いは、イベントハンドラーの使い方にある。ＥＤＰでは、任意の数のタイマーを利用することができるのに対し、ＣＤＰでは、タイマーイベントハンドラーを提供するタイマーを、必ず１つ利用することが要求される。
【００２３】
また、ＥＤＰでは、タイマーイベントハンドラーを含むすべてのイベントハンドラーにおいて、イベントに対応する処理を行う。一方、ＣＤＰでは、タイマーイベントハンドラー以外のイベントハンドラーにおいて、状態を示すフラグをセットすることにより、イベントの発生を記録するのみで、イベントに対応する処理は、ここでは行わない。ＣＤＰでは、タイマーイベントハンドラーにおいて、状態を示すフラグに基づいて、イベントの発生に対応するタスクを実行する。
【００２４】
ＣＤＰプログラムは、以下の手順で作成される。１）タスクを洗い出し、記述する。２）タスク間の先行関係を把握し、ＰＥＲＴ図を作成する。３）ＰＥＲＴ図によって与えられた先行関係の制約を満たすスケジュールを作成する。タスクの記述、ＰＥＲＴ図の作成、スケジュールの作成を順に説明する。
【００２５】
（タスクの記述）
ＣＤＰのタスクを、図２のプログラム記述例に基づいて説明する。ＣＤＰのタスクは、以下の要素を用いて定義される。
内部変数：ステート間で値を引継ぐために使用する１以上の変数
インタフェース関数：内部変数を他のタスクが参照または更新するための０以上の関数
リセット関数：内部変数を初期化するための関数
タスク本体関数：タイマーイベントハンドラーによって呼び出される関数
【００２６】
ＣＤＰのタスクは、状態により、実行する動作が変化するステートマシンである。ステート間で値を引継ぐために、内部変数を用いる。図２の例では、行番号L5に、taskA_data_t構造体型の内部変数taskA_dataが定義されている。なお、taskA_data_t構造体型は、同図の行番号L2からL4により示されるように、taskA_state_t列挙型の変数state、int型のx、y、resultをメンバとして含む。
【００２７】
ＣＤＰのタスクは、前述の内部変数を他のタスクが参照または更新するためのインタフェース関数を必要に応じて定義する。図２の例では、行番号L13からL31で定義されるcalcメソッド、行番号L33からL43で定義されるget_resultメソッドがインタフェース関数である。calcメソッドは、図２に記述されるTaskAに処理を要求するための関数、get_resultメソッドは、処理結果を要求するための関数である。
【００２８】
ＣＤＰのタスクはまた、内部変数を初期化するためのリセット関数を定義する。図２の例では、行番号L45からL48で定義されるtaskA_RSTメソッドがリセット関数である。本実施形態では、リセット関数において内部変数taskA_dataのメンバ変数stateを初期化している。
【００２９】
そして、ＣＤＰのタスクは、タイマーイベントハンドラーによって呼び出されるタスク本体関数を定義する。図２の例では、行番号L50からL84で定義されるtaskA_CLKメソッドがタスク本体関数である。図２に示されるように、タスク本体関数は、taskA_data.stateの値に従って計算を実行する。stateがcalc1の場合、Ｆ（ｘ）を計算する。ここで、関数Fは、行番号L11で定義されるように、標準ライブラリなどの他のモジュールで定義される外部関数である。stateがcalc2の場合、定数LIMITを上限として、Ｆ（ｘ）yを計算する。
【００３０】
ここで、タスクの実行時間は、タイマーの周期より短い必要がある。そのため、タスクは次の２つの要求を満たす必要がある。１）タスクは、実行ステップの上限を有する。２）タスクの各ステートメントは、実行時間の上限を有する。
【００３１】
要求１）を満たすために、各関数は、構文的に停止性が保証される形で書く。すなわち、選択(if then else)および順次（;) の組み合わせに展開可能となるように記述する。ループに関しては、反復回数に上限があるものだけが記述可能であり、実行時に反復回数が決まるループを書くことは許されない。不定回数のループは、図２のtaskA_CLKメソッドのように、固定回数のループを周期的に実行することにより実現する。この場合、選択（if then else)によりステップ数は変化するが、１周期で実行されるステップ数には上限が存在するので、要求１）が満たされる。
【００３２】
要求２）を満たすために問題となるのは、ステートメントが関数呼び出しを含む場合である。呼び出す関数が他のタスクのインタフェース関数である場合は、呼び出し先の関数についても実行ステップ数に上限があり、結果として実行時間に上限があるので、問題はない。一方、呼び出す関数が、ライブラリ関数やＯＳの機能を呼び出すＡＰＩなど、ＣＤＰに従わない関数である場合、実行時間に上限がない場合がある。
【００３３】
特に問題となるのが、ＯＳのＡＰＩに存在するblocking I/Oである。例えば、blocking I/O のREAD関数を用いてファイルの読み出しをする場合、ファイルの読み出しが完了するまで、呼び出し側プログラムに制御を戻さない。これでは、要求２）を満たすことができない。そこで、ＣＤＰのタスクでは、原則としてblocking I/Oの代わりに、non-blocking I/Oを用いる。あるいは、select関数等を用いてブロックされないことを確認した上でblocking I/Oを用いる。
【００３４】
続いて、図３に、図２に記載のtaskAを利用するtaskBのプログラム記述例を示す。taskBは、列挙型の変数state、int型のa、b、zをメンバとして含む構造体型の内部変数taskB_dataを持つ。taskBのタスク本体関数では、図３の行番号L34に示されるように、stateがstate_10の場合、calcメソッドを呼ぶことによりtaskAに処理を要求する。図２の行番号L23に示されるように、taskAの状態に従って要求が受け入れられる場合のみ、戻り値として0が返される。従って、taskBは、要求が受け入れられるまでリトライし、要求が受け入れられると、state_11に遷移する。
【００３５】
また、図３の行番号L40に示されるように、stateがstate_11の場合、get_resultメソッドを呼ぶことにより処理結果の取得を試みる。ここでも、図２の行番号L40に示されるように、taskAの状態に従って計算が終わっている場合のみ、戻り値として0が返される。従って、taskBは、戻り値として0が得られるまで、クロック毎にget_resultメソッドを呼び出し、処理結果を取得すると、state_12に遷移する。
【００３６】
（タスクの配列化）
図２の行番号L18に示されるように、taskAはstateがfreeである場合のみ、計算要求を受け入れる。つまり、taskAが先行する計算要求を受け入れ、計算を実行している間は、他のタスクからの計算要求を受け入れることはできない。そこで、同時に複数の計算要求を処理したい場合には、同一機能を持つ複数のタスクを用意するために、タスクを配列化したタスク配列を定義する。図４に、図２に記載のtaskAを配列化したタスク配列のプログラム記述例を示す。
【００３７】
図４の行番号L4に示されるように、タスク配列では、内部変数を配列化する。そして、行番号L7に示されるように、インタフェース関数calcの引数としてインデクスを受け取り、内部変数の参照、更新時には受け取ったインデクスを指定して行う。他の関数においても、同様に引数としてインデクスを受け取り、受け取ったインデクスを指定して内部変数の参照更新を行うことにより、タスクを配列化することができる。内部変数配列の要素数をタスク配列の多重度と呼び、配列化されていないタスク（例えば、図２のtaskA）の多重度は１である。
【００３８】
（ＰＥＲＴ図の作成）
タスクを記述したら、次にタスク間の先行関係を把握しＰＥＲＴ図を作成する。タイマーイベントハンドラーが呼び出すのは、タスク本体関数であり、タスク間の先行関係とは、タスク本体関数間の先行関係である。あるタスクは、そのタスク本体関数において、他のタスクのインタフェース関数を呼び出して、他のタスクの処理結果を取得する。例えば、図３に示すtaskBは、タスク本体関数において、taskAのget_resultメソッドを呼び出して、taskAの処理結果Ｆ（ｘ）yを取得する。このインタフェース関数の静的呼び出し関係を示したものが、図５のコールグラフである。
【００３９】
ここで、taskBが処理結果を得るためには、taskAのタスク本体関数がtaskBのタスク本体関数の実行の前に完了している必要がある。この場合、taskAはtaskBに先行する。完了順序を示すＰＥＲＴ図は、コールグラフの矢印の向きを逆転することにより得ることができる（図６）。しかし、全てのコールグラフからＰＥＲＴ図を得ることができるわけではない。
【００４０】
ＰＥＲＴ図を得るためには、コールグラフがacyclicである（ループがない）必要がある。図７に示すように、コールグラフがacyclicでない場合は、ポーリング（polling）を用いてタスク間のインタフェースの向きを入れ替える必要がある。taskAとtaskBとのコールグラフはacyclicであるので、タスク間のインタフェースの向きを入れ替える必要はない。ポーリングを用いる参考例として、図８Ａおよび図８Ｂに、インタフェース方向を変えたtaskAおよびtaskBのプログラム記述例を示す。
【００４１】
得られたＰＥＲＴ図から、同時実行され得るタスクを判断することができる。コールグラフに基づいて、図９に示すＰＥＲＴ図が得られたものとする。ここで、図９に示すＰＥＲＴ図のグラフＧは、１から９のタスクに対応するノードの集合、およびタスク間の先行関係を表す矢印の集合により構成される。ＰＥＲＴ図には、本来のタスク１から９に対応するノードに加えて、プログラム全体のスタートとフィニッシュをそれぞれ表す端点sと端点tが記されている。
【００４２】
図１０に、図９のＰＥＲＴ図に含まれるタスク間の先行関係を示す先行関係表を示す。図中の◎は、２つのタスクが、直接の先行関係を有することを示す。例えば、タスク１と（タスク１のインタフェース関数を呼び出す）タスク４、タスク１と（タスク１のインタフェース関数を呼び出す）タスク６などは、直接の先行関係を有する。図中の○は、２つのタスクが、間接の先行関係を有することを示す。例えば、タスク１とタスク７、タスク１とタスク８、タスク１とタスク９などは、間接の先行関係を有する。図中の×は、２つのタスクが、先行関係を有し得ないことを示す。
【００４３】
間接の先行関係は、直接の先行関係を有さないが、１または複数のタスクを経由して先行関係を有する２つのタスク間において生じる。例えば、タスク１とタスク７は、タスク１のインタフェース関数を呼び出し、かつタスク７によりそのインタフェース関数を呼び出されるタスク４を経由して、先行関係を有する。同様に、タスク１とタスク８も、タスク４を経由して先行関係を有する。また、タスク１とタスク９は、タスク４およびタスク７を経由して、あるいはタスク６を経由して、先行関係を有する。
【００４４】
ここで、特定のタスクｖのインタフェース関数を呼び出すタスクｕ、およびタスクｗが、直接または間接の先行関係を有する場合、タスクｕとタスクｗとは、同時実行されることはない。例えば、タスク１のインタフェース関数を呼び出すタスク４およびタスク６は、図１０に示されるように直接の先行関係を有するので、同時実行されることはない。一方、タスク３のインタフェース関数を呼び出すタスク５およびタスク８は、図１０に示されるように先行関係を有さないので、同時実行され得る。
【００４５】
複数のタスクが同時に同じタスクのインタフェース関数を呼び出す場合、タスクの実行される順序やインタフェース関数の実行される順序により、結果が変わってしまう可能性がある。そこで、複数のタスクから同時に呼び出され得るインタフェース関数は、Bernstein’s conditionsを満たす必要がある。Bernstein's conditionsは、プログラムの断片が並列実行できるための、周知の十分条件である。
【００４６】
例えば、タスク５およびタスク８から同時に呼び出され得る、タスク３に含まれる関数ｆ、ｇは、関数ｆの中で構文的に参照される内部変数の集合（Ｒ（ｆ））、関数ｆの中で構文的に代入される内部変数の集合（Ｗ（ｆ））、関数ｇの中で構文的に参照される内部変数の集合（Ｒ（ｇ））、および関数ｇの中で構文的に代入される内部変数の集合（Ｗ（ｇ））について以下の(1)から(3)が成り立つ場合、Bernstein's conditionsを満たし、並列実行することができる。
R(f) ∩ W(g) ＝ φ・・・(1)  
R(g) ∩ W(f) ＝ φ・・・(2)  
W(f) ∩ W(g) ＝ φ・・・(3)
【００４７】
（Bernstein's conditionsを満たすプログラムへの書き換え技法）
同時実行され得るタスクがBernstein's conditionsを満たさない場合、書き替え技法を用いてプログラムを修正する必要がある。代表的な３つの書き換え技法を以下で紹介する。
【００４８】
第１の書き替え技法として、変数リネーム技法がある。図１１Ａおよび図１１Ｂに、変数リネーム技法を適用する前後のプログラム記述例を示す。適用前のプログラム記述例では、図１１Ａに示されるように、インタフェース関数read、writeにおいて、Ｒ（read） ∩ Ｗ（write） ＝ {taskA_x} ≠ φであり、Bernstein's conditionsを満たさない。一方、適用後のプログラム記述例では、図１１Ｂに示されるように、別途内部変数を用いてプログラムを修正することにより、Ｒ（read） ∩ Ｗ（write） ＝φとなり、Bernstein's conditionsを満たすことができる。
【００４９】
第２の書き替え技法として、個別化技法がある。個別化技法では、Bernstein's conditionsを満たさないインタフェース関数を有するタスクを、配列化する。図１２に、個別化技法を適用する前後のコールグラフを示す。適用前のコールグラフでは、図１２（左）に示されるように、インタフェース関数calc_Fの競合がおき、Ｒ（calc_F） ∩ Ｗ（calc_F） ＝ {taskB_data} ≠ φであり、Bernstein's conditionsを満たさない。一方、適用後のコールグラフでは、図１２（右）に示されるように、taskBを配列化することにより、Ｒ（calc_F(0)) ∩ ）Ｗ（calc_F(1)） ＝ {taskB_data[0]} ∩ {taskB_data[1]} ＝ φとなり、Bernstein's conditionsを満たすことができる。
【００５０】
第３の書き替え技法として、抽選化技法がある。前述した個別化技法は、唯一のリソースを使用する場合には適用することができない。この場合、内部変数のみを配列化し、タスクは配列化しない抽選化技法により、インタフェース関数の競合を防ぐ。具体的には、図１３Ａに示されるように、競合対象であるtaskBのタスク本体関数において、複数のインタフェース関数呼び出しのうちの１つを選択し（抽選）、選択された（当選した）呼び出しのみ処理を実行し、選択されなかった（落選した）呼び出しについてはエラーを返す。また、図１３Ｂに示されるように、呼び出し側タスクであるtaskC（およびtaskD（図示せず））では、当選するまでインタフェース関数の呼び出しを繰り返す。
【００５１】
（スケジュールの作成）
ＰＥＲＴ図が得られたら、次にスケジュールを作成する。スケジュールは、どのタイミングでどのリソースにタスクを割り当てるかを、ＰＥＲＴ図で与えられた先行関係を満たすように定めたものである。利用可能なリソースの制約の元で、完了時間が最小となるスケジュールを作成することが望ましい。図１４に示すＰＥＲＴ図に基づいて、スケジュールを作成する。
【００５２】
（スケジュールの作成−逐次実行）
逐次実行する場合、ＰＥＲＴ図を既知のアルゴリズムでトポロジカルソートすることにより、容易にスケジュールを作成することができる。図１４のＰＥＲＴ図の場合、以下の３つのスケジュールが作成される。taskX、taskY、taskZ、taskWのタスク本体関数が、それぞれ、taskX_CLK()、taskY_CLK()、taskZ_CLK()、taskW_CLK()であるものとする。  
スケジュール１＝taskX_CLK(); taskY_CLK(); taskW_CLK(); taskZ_CLK();
スケジュール２＝taskX_CLK(); taskY_CLK(); taskZ_CLK(); taskW_CLK();
スケジュール３＝taskX_CLK(); taskZ_CLK(); taskY_CLK(); taskZ_CLK();
【００５３】
ＰＥＲＴ図の先行関係を満たす限り、どの順序で実行しても同一の結果を得ることができ、また、同一の完了時間となる。従って、任意のスケジュールを選択することができる。図１５に、スケジュール１でタスクを実行するプログラム記述例を示す。図１５の行番号L25において、第３引数（presiod）で指定した100ミリ秒ごとに、第４引数（OnTimer）で指定した関数が呼ばれるよう、タイマーの設定が行われている。本実施形態ではスケジュール１を実行するために、図１５の行番号L6からL9に示されるように、タスクの実行順序を定義する。
【００５４】
（スケジュールの作成−並列実行）
並列実行する場合、タスク間の先行関係は同期プリミティブを用いて実現する。本実施形態では、同期プリミティブとして、Windowsの提供するEvent Objectを用いる。Event Objectは、２つの状態（シグナル状態／非シグナル状態）を持つ。SetEvent(e)を呼び出すことにより、引数eのハンドルにより特定されるEvent Objectはシグナル状態になる。WaitForSingleObject(e)を呼び出すと、引数eのハンドルにより特定されるEvent Objectが非シグナル状態である場合、シグナル状態になるまでWaitForSingleObject(e)の呼び出し側スレッドは待機し続ける。他のスレッドによりSetEvent(e)が呼ばれ、eにより特定されるEvent Objectがシグナル状態になると、制御が戻され、呼び出し側スレッドは後続の処理を実行することができる。
【００５５】
例えば、図１４のＰＥＲＴ図を、並列度４で実行する場合を考える。  
スケジュール４−０＝taskX_CLK(); SetEvent(e1); SetEvent(e2);
スケジュール４−１＝WaitForSingleObject(e1); taskZ_CLK();
スケジュール４−２＝WaitForSingleObject(e2); taskY_CLK(); SetEvent(e3);
スケジュール４−３＝WaitForSingleObject(e3); taskW_CLK();
【００５６】
スケジュール４−０では、taskX_CLKメソッドが完了すると、e1およびe2により特定されるEvent Objectをシグナル状態にする。スケジュール４−１では、WaitForSingleObject(e1)を呼び出し、e1により特定されるEvent Objectがシグナル状態になるまで、待機し続ける。taskX_CLKメソッドの完了によりSetEvent(e1)が呼ばれると、スケジュール４−１に対応するスレッドに制御が戻され、taskZ_CLKメソッドが実行される。同様に、スケジュール４−２では、WaitForSingleObject(e2)を呼び出し、e2により特定されるEvent Objectがシグナル状態になるまで、待機し続ける。taskX_CLKメソッドの完了によりSetEvent(e2)が呼ばれると、スケジュール４−２に対応するスレッド制御が戻され、taskY_CLKメソッドが実行される。スケジュール４−２では、taskY_CLKメソッドが完了すると、e3により特定されるEvent Objectをシグナル状態にする。スケジュール４−３も、WaitForSingleObject(e3)を呼び出し、e3により特定されるEvent Objectがシグナル状態になるまで、待機し続ける。taskY_CLKメソッドの完了によりSetEvent(e3)が呼ばれると、スケジュール４−３に対応するスレッドに制御が戻され、taskW_CLKメソッドが実行される。
【００５７】
図１６に、スケジュール４−０から４−３でタスクを実行するプログラム記述例を示す。図１６の行番号L43において、第３引数（presiod）で指定した100ミリ秒ごとに、第４引数（OnTimer）で指定した関数が呼ばれるよう、タイマーの設定が行われている。本実施形態では、図１６の行番号L3からL14に示されるように、スケジュール４−１から４−３に対応するスレッドを用意する。
【００５８】
OnTimerメソッドでは、まず、スレッド１、スレッド２、スレッド３にそれぞれ対応するs[0]、s[1]、s[2]により特定されるEvent Objectをシグナル状態にする。その後、メインスレッドでスケジュール４−０を実行し、スレッド１、スレッド２、スレッド３にそれぞれ対応するt[0]、t[1]、t[2]により特定されるEvent Object のWaitForSingleObjectメソッドを呼び出すことで、Event Objectがシグナル状態になるまで、すなわち該当のスレッドが完了するまで待機し続ける。図１７に、並列実行のシーケンス図を示す。
【００５９】
スケジュール４−１に対応するスレッド１では、WaitForSingleObject(s[0])を呼び出し、s[0]により特定されるEvent Objectがシグナル状態になるまで、待機し続ける。図１６の行番号L18に示されるように、OnTimerメソッド内でSetEvent(s[0])が呼ばれると、スレッド１に制御が戻され、WaitForSingleObject(e1)を呼び出す。その後、e1により特定されるEvent Objectがシグナル状態になるまで、待機し続ける。taskX_CLKメソッドの完了によりSetEvent(e1)が呼ばれると、スレッド１に制御が戻され、taskZ_CLKメソッドが実行される。スレッド１では、taskZ_CLKメソッドが完了すると、t[0]により特定されるEvent Objectをシグナル状態にすることで、スレッドの完了を通知する。
【００６０】
スケジュール４−２に対応するスレッド２（図示せず）においても、スレッド１同様、WaitForSingleObject(s[1])を呼び出し、s[1]により特定されるEvent Objectがシグナル状態になるまで、待機し続ける。図１６の行番号L19に示されるように、OnTimerメソッド内でSetEvent(s[1])が呼ばれると、スレッド２に制御が戻され、WaitForSingleObject(e2)を呼び出す。その後、e2により特定されるEvent Objectがシグナル状態になるまで、待機し続ける。taskX_CLKメソッドの完了によりSetEvent(e2)が呼ばれると、スレッド２に制御が戻され、taskY_CLKメソッドが実行される。スレッド２では、taskY_CLKメソッドが完了すると、taskYの完了を通知するSetEvent(e3)を呼び出し、その後、t[1]により特定されるEvent Objectをシグナル状態にすることで、スレッドの完了を通知する。
【００６１】
スケジュール４−３に対応するスレッド３（図示せず）においても、スレッド１同様、WaitForSingleObject(s[2])を呼び出し、s[2]により特定されるEvent Objectがシグナル状態になるまで、待機し続ける。図１６の行番号L20に示されるように、OnTimerメソッド内でSetEvent(s[2])が呼ばれると、スレッド３に制御が戻され、WaitForSingleObject(e3)を呼び出す。その後、e3により特定されるEvent Objectがシグナル状態になるまで、待機し続ける。taskY_CLKメソッドの完了によりSetEvent(e3)が呼ばれると、スレッド３に制御が戻され、taskW_CLKメソッドが実行される。スレッド３では、taskW_CLKメソッドが完了すると、t[2]により特定されるEvent Objectをシグナル状態にすることで、スレッドの完了を通知する。
【００６２】
（スケジュールの作成−タスク配列）
タスク配列内の各タスク間に先行関係は存在しない。そのため、各タスクをどのような順序でスケジューリングしてもよい。また、タスク配列は、コードは全て同じで、内部変数の場所だけが異なるので、タスク配列内の各タスクの平均の実行時間は、同一であることが期待できる。従って、タスクの多重度がｍ、利用可能なＣＰＵ数がｎである場合、各ＣＰＵにｍ／ｎ個ずつタスクを分配する。
【００６３】
図１４に示すＰＥＲＴ図のtaskYが多重度４のタスク配列で、利用可能なＣＰＵ数が５である場合、以下のスケジュールを作成することができる。  
スケジュール５−０＝taskX_CLK(); SetEvent(e1); SetEvent(e21); SetEvent(e22);
スケジュール５−１＝WaitForSingleObject(e1); taskZ_CLK();
スケジュール５−２＝WaitForSingleObject(e21); taskY_CLK(0); taskY_CLK(2); 
SetEvent(e31);
スケジュール５−３＝WaitForSingleObject(e22); taskY_CLK(1); taskY_CLK(3); 
SetEvent(e32);
スケジュール５−４＝WaitForSingleObject(e31); WaitForSingleObject(e32); 
taskW_CLK();
【００６４】
このように、多重度の数だけ存在するタスク本体関数をインデックス指定して、各ＣＰＵに分配することにより、利用可能なＣＰＵ数に応じてスケジュールを作成することができる。
【００６５】
ここまで、ＣＤＰプログラムについて詳述してきた。特に、スケジュールの作成に関する章では、ＰＥＲＴ図で与えられた先行関係を満たすスケジュールの作成について述べている。前述したように、逐次実行する場合、ＰＥＲＴ図を既知のアルゴリズムでトポロジカルソートすることにより、容易にスケジュールを作成することができる。しかし、並列実行する場合については、有用なスケジュール作成技術が、現在示されていない。以降の章では、実行時間が特定されない複数のタスクを、そのタスク間の先行関係のみに基づいてスケジューリングする技術を開示する。
【００６６】
（システム構成）
図１８のブロック図を参照して、スケジュール作成システム１の構成を詳細に説明する。なお、図１８では、単一のコンピュータシステムを想定し、必要な機能構成だけを示しているが、スケジュール作成システム１を、複数のコンピュータシステムによる多機能の分散システムの一部として構成することもできる。
【００６７】
スケジュール作成システム１は、ＣＰＵ１０に、システムバス１１を介してＲＡＭ１２、入力装置１３、出力装置１４、通信制御装置１５および不揮発性記憶媒体（ＲＯＭやＨＤＤなど）で構成される記憶装置１６が接続された構成を有する。記憶装置１６は、上記した機能を奏するためのソフトウェアプログラムを格納するプログラム格納領域と、随時取得するデータや処理結果としてのデータ等を格納するデータ格納領域とを備えている。以下に説明するプログラム格納領域の各手段は、実際は独立したソフトウェアプログラム、そのルーチンやコンポーネントなどであり、ＣＰＵ１０によって記憶装置１６から呼び出されＲＡＭ１２のワークエリアに展開されて、データベース等を適宜参照しながら順次実行されることで、各機能を奏するものである。
【００６８】
データ格納領域は、閉包先行関係記憶手段１７、縮退先行関係記憶手段１８、タスク配置記憶手段１９およびイベント記憶手段２０を備える。何れも、記憶装置１６内に確保された一定の記憶領域である。
【００６９】
閉包先行関係記憶手段１７および縮退先行関係記憶手段１８は、図１９および図２０に示すように、先行タスク、後続タスク、先行関係タイプを格納する。本実施形態では、先行関係タイプには、直接の先行関係を示す２、または間接の先行関係を示す１のいずれかを格納する。
【００７０】
タスク配置記憶手段１９は、ｍ個のレイヤ、およびｎ個のレベルを有し、ｍ×ｎ個の領域に分割されるタスク配置構造体を格納する。各領域には、０または１つのタスクが格納される。レイヤおよびレベルについては後述する。
【００７１】
イベント記憶手段２０は、図２１に示すように、通知タスク、待機タスク、イベント識別子を格納する。通知タスクにタスクｘ、および待機タスクにタスクｙが格納される場合、タスクｘの実行完了後にタスクｙを実行すべきであることがわかる。イベント識別子は、イベントを一意に識別する。
【００７２】
プログラム格納領域に格納されているソフトウェアプログラムは、本発明に関連するものだけを列挙すると、先行関係管理手段２１、タスク配置手段２２、イベント識別手段２３およびスケジュール変換手段２４を備えている。
【００７３】
先行関係管理手段２１は、スケジュール作成対象のプログラムのタスク間の先行関係データを受信する。一実施形態では、先行関係データの一例であるＰＥＲＴ図を受信する。また、先行関係管理手段２１は、受信した先行関係データからタスクに対応するノードの集合、およびタスク間の先行関係を表す矢印の集合を抽出する。先行関係管理手段２１は、タスク間に生じる間接の先行関係を識別する。間接の先行関係については後述する。先行関係管理手段２１は、タスク間の直接の先行関係および間接の先行関係に基づいて、受信した先行関係データの推移閉包（Transitive Closure）を閉包先行関係記憶手段１７に、および受信した先行関係データの推移縮退（Transitive Reduction）を縮退先行関係記憶手段１８に登録する。
【００７４】
タスク配置手段２２は、ＰＥＲＴ解析を使用して、各タスクの実行時間を１とした場合の各タスクの最速開始時間を算出する。タスク配置手段２２は、算出した開始時間に基づいて、スタート時間、各開始時間、およびフィニッシュ時間に対応するレイヤを有するタスク配置構造体を生成する。
【００７５】
タスク配置手段２２は、レイヤＬおよびレイヤＬ−１内のタスク数を比較して、いずれか一方のレイヤ内のタスク数が他方のレイヤ内のタスク数より少ない場合、空タスクを生成して両レイヤ内のタスク数を同一にする。空タスクについては後述する。また、タスク配置手段２２は、閉包先行関係記憶手段１７に基づいて、レイヤＬ−１内の各タスクに対して、後続となり得るレイヤＬ内のタスク（後続タスク候補）の集合を判定する。タスク配置手段２２は、グラフの最大マッチングアルゴリズムを用いて、レイヤＬ−１内の各タスクとその後続タスクについて、最大マッチングを取得する。
【００７６】
タスク配置手段２２は、得られた最大マッチングのマッチング数とレイヤＬ−１内のタスク数を比較する。マッチング数がタスク数より少ない場合、マッチング数とタスク数の差の数、レイヤＬおよびレイヤＬ−１に空タスクを生成し、空タスクを配置するために、新たなレベルの領域を作成する。マッチング数とタスク数とが一致する場合には、各タスクを配置する領域をレイヤＬ内に作成し、作成した領域にタスクを配置する。
【００７７】
イベント識別手段２３は、レイヤＬ−１内のタスクｘの後続としてレイヤＬ内に配置できなかったタスクｙを識別し、イベント記憶手段２０に記憶する。なお、レイヤＬ−１内のタスクｘの後続としてレイヤＬ内に配置できなかったタスクｙが存在する場合であっても、タスクｘの後続として空タスクが配置されている場合には、この空タスクの後続としてタスクｙが配置されないときのみ、イベント記憶手段２０に記憶する。
【００７８】
スケジュール変換手段２４は、タスク構造体のレベルのうち、スケジュールを作成していないレベルを抽出する。スケジュール変換手段２４は、レイヤＣに配置されたタスクを識別する。スケジュール変換手段２４は、イベント記憶手段２０に基づいて、識別したタスクを実行する前に待機すべきイベントが存在するか否かを判定する。待機すべきイベントが存在する場合は、待機すべきイベントをスケジュールとして記述する。一実施形態では、Event Objectを用いて待機すべきイベントを記述する。
【００７９】
スケジュール変換手段２４は、識別したタスクが空タスクでない場合、当該タスクの実行をスケジュールとして記述する。スケジュール変換手段２４は、イベント記憶手段２０に基づいて、識別したタスクの完了を通知すべきイベントが存在するか否かを判定する。通知すべきイベントが存在する場合は、通知すべきイベントをスケジュールとして記述する。一実施形態では、Event Objectを用いて通知すべきイベントを記述する。
【００８０】
（スケジュール作成方法−タスク配置構造体の作成）
次に、図２２のフローチャートを参照して、本実施形態に係るスケジュールを作成する工程を説明する。本実施形態では、図９に示されるＰＥＲＴ図で表される複数のタスクを、そのタスク間の先行関係のみに基づいてスケジューリングする。
【００８１】
処理Ｓ１において、先行関係管理手段２１は、スケジュール作成対象のプログラムのタスク間の先行関係データを受信する。本実施形態では、先行関係データの一例である、図９に示されるＰＥＲＴ図を受信したものとする。この先行関係データは、コンピュータを介してユーザーから、または外部のシステムなどから受信することができる。
【００８２】
処理Ｓ２において、先行関係管理手段２１は、受信した先行関係データからタスクに対応するノードの集合、およびタスク間の先行関係を表す矢印の集合を抽出する。本実施形態では、タスク１からタスク９の計９個のタスクに対応するノード、およびタスク１からタスク４への先行関係を示す矢印＜１，４＞、タスク１からタスク６への先行関係を示す矢印＜１，６＞、・・・など、計１２個の矢印が抽出される。
【００８３】
処理Ｓ３において、先行関係管理手段２１は、タスク間に生じる間接の先行関係を識別する。本実施形態では、タスク４を経由して先行関係を有するタスク１とタスク６との間、タスク４を経由して先行関係を有するタスク１とタスク７との間、などに生じる間接の先行関係が識別される。
【００８４】
処理Ｓ４において、先行関係管理手段２１は、処理Ｓ２で抽出したタスク間の直接の先行関係、および処理Ｓ３で識別したタスク間の間接の先行関係に基づいて、受信した先行関係データの推移閉包を閉包先行関係記憶手段１７に、および受信した先行関係データの推移縮退を縮退先行関係記憶手段１８に登録する。本実施形態では、図１９および図２０に示されるようなレコードが登録される。
【００８５】
閉包先行関係記憶手段１７には、先行関係を有するすべてのタスク間のレコードが登録される。ここで、例えばタスク１とタスク６とは、図９に示されるように直接の先行関係を有し、かつ、前述したように間接の先行関係も有する。すなわち、タスク１がタスク６に先行することは、タスク１とタスク６との直接の先行関係によって表されており、かつ、タスク１とタスク４との直接の先行関係およびタスク４とタスク６との直接の先行関係によっても表されている。このように、直接の先行関係および間接の先行関係を有する場合には、間接の先行関係を優先して登録する。このようにすることで、直接の先行関係のうち、他の直接の先行関係によって表される冗長関係を排除することができる。
【００８６】
また、縮退先行関係記憶手段１８には、閉包先行関係記憶手段１７に登録されているレコードのうち、直接の先行関係を示すレコードのみが登録される。図２３に、処理Ｓ４時点のＰＥＲＴ図を示す。図２３に示されるように、処理Ｓ４時点では、タスク１とタスク６との直接の先行関係を示す矢印は削除される。
【００８７】
次に、処理Ｓ５において、タスク配置手段２２は、縮退先行関係記憶手段１８に記録された先行関係に対し、ＰＥＲＴ解析を使用して、各タスクの実行時間を１とした場合の各タスクの最速開始時間を算出する。本実施形態では、プログラム全体のスタートを０とし、実行時間１にタスク１、タスク２、タスク３が開始され、実行時間２にタスク４、タスク５が開始され、実行時間３にタスク６、タスク７、タスク８が開始され、実行時間４にタスク９が開始され、フィニッシュすることがわかる。
【００８８】
処理Ｓ６において、タスク配置手段２２は、処理Ｓ５で算出した開始時間に基づいて、スタート時間、各開始時間、およびフィニッシュ時間に対応するレイヤを有するタスク配置構造体を生成する。本実施形態では、計６個のレイヤを有するタスク配置構造体が生成される。図２４は、タスク構造体に配置されているＰＥＲＴ図のイメージ図である。
【００８９】
処理Ｓ７において、タスク配置手段２２は、レイヤ１の割り当てを決定する。具体的には、レイヤ１をレイヤ内に存在するタスク数のレベルに分割し、分割した領域にタスクを配置する。本実施形態では、レイヤ１内にタスクが３つ存在するので、レイヤ１を３つのレベルに分割して、タスク１、タスク２、タスク３を配置する。図２５は、処理Ｓ７時点のタスク構造体に配置されたＰＥＲＴ図のイメージ図である。レイヤ１の割り当て完了後、タスク配置手段２２は、レイヤＬにレイヤ２をセットする。
【００９０】
処理Ｓ８において、タスク配置手段２２は、レイヤＬがフィニッシュ時間に対応するレイヤｔであるか否か判定する。レイヤｔでない場合、処理Ｓ９に進み、レイヤｔである場合には処理Ｓ１７に進む。本実施形態では、レイヤＬはレイヤ２であるので、処理Ｓ９に進む。
【００９１】
処理Ｓ９において、タスク配置手段２２は、レイヤＬおよびレイヤＬ−１内のタスク数を比較して、いずれか一方のレイヤ内のタスク数が他方のレイヤ内のタスク数より少ない場合、空タスクを生成して両レイヤ内のタスク数を同一にする。本実施形態では、レイヤＬ（レイヤ２）内のタスク数が２、レイヤＬ−１（レイヤ１）内のタスク数が３であるので、レイヤ２に空タスクを１つ生成する。図２６は、処理Ｓ９時点のタスク構造体に配置されたＰＥＲＴ図のイメージ図である。図２６において、空タスクはεとして表される。空タスクは、スケジュール作成のために用いる、実行ステップを持たないタスクである。
【００９２】
処理Ｓ１０において、タスク配置手段２２は、閉包先行関係記憶手段１７に基づいて、レイヤＬ−１内の各タスクに対して、後続となり得るレイヤＬ内のタスク（後続タスク候補）の集合を判定する。ここで、タスクｘおよびタスクｙが先行関係を有する場合、タスクｙはタスクｘの後続となり得る。また、空タスクは、任意のタスクの後続になり得る。本実施形態では、タスク１の後続タスク候補としてタスク４および空タスク１、タスク２の後続タスク候補としてタスク４および空タスク１、タスク３の後続タスク候補としてタスク５および空タスク１が判定される。
【００９３】
処理Ｓ１１において、タスク配置手段２２は、グラフの最大マッチングアルゴリズムを用いて、レイヤＬ−１内の各タスクとその後続タスクについて、最大マッチングを取得する。本実施形態では、組み合わせ１｛［タスク１→タスク４］，［タスク２→空タスク１］，［タスク３→タスク５］｝および組み合わせ２｛［タスク１→空タスク１］，［タスク２→タスク４］，［タスク３→タスク５］｝の２通りの最大マッチングが得られる。
【００９４】
処理Ｓ１２において、タスク配置手段２２は、処理Ｓ１１で得られた最大マッチングのマッチング数とレイヤＬ−１内のタスク数を比較する。マッチング数がタスク数より少ない場合、処理Ｓ１３に進み、マッチング数とタスク数とが一致する場合には、処理Ｓ１４に進む。本実施形態では、マッチング数およびタスク数が３と一致するので、処理Ｓ１４に進む。処理Ｓ１３については後述する。
【００９５】
処理Ｓ１４において、タスク配置手段２２は、レイヤＬをレイヤ内に存在するタスク数のレベルに分割し、分割した領域にタスクを配置する。ここで、レイヤＬおよびレイヤＬ−１は同じ数の領域が作成されている。図２７に示すように、タスク配置構造体を区切る縦の単位をレイヤ、横の単位をレベルと呼ぶ。タスク配置手段２２は、各タスクとその後続のタスクとが、同一レベルになるようにタスクを配置する。処理Ｓ１１で複数の最大マッチングが得られた場合には、任意の１つを選択することができる。本実施形態では、組み合わせ１を選択し、レイヤ２のレベル１にタスク４を、レイヤ２のレベル２に空タスク１を、レイヤ２のレベル３にタスク５を配置する。図２７は、処理Ｓ１４時点のタスク構造体に配置されたＰＥＲＴ図のイメージ図である。
【００９６】
処理Ｓ１５において、イベント識別手段２３は、レイヤＬ−１内のタスクｘの後続としてレイヤＬ内に配置できなかったタスクｙを識別し、イベント記憶手段２０に記憶する。本実施形態では、まず、タスク２の後続として配置できなかったタスク４が識別され、イベント記憶手段２０に記憶される。また、レイヤ１内のタスク３の後続としてレイヤ２内に配置できなかったタスク８が識別され、イベント記憶手段２０に記憶される。ここでは、図２１のイベント識別子e0およびe1により識別されるレコードが登録される。
【００９７】
処理Ｓ８から処理Ｓ１５までが、１つのレイヤに対する処理である。処理Ｓ１６において、タスク配置手段２２は、レイヤＬに現在処理中のレイヤの次のレイヤをセットし、処理Ｓ８に戻る。本実施形態では、タスク配置手段２２は、レイヤＬにレイヤ３をセットし、処理Ｓ８に戻る。
【００９８】
本実施形態では、処理Ｓ８（２週目）において、タスク配置手段２２は、レイヤＬがフィニッシュ時間に対応するレイヤｔであるか否か判定し、レイヤＬはレイヤ３であるので、処理Ｓ９に進む。
【００９９】
処理Ｓ９（２週目）において、タスク配置手段２２は、レイヤ３およびレイヤ２内のタスク数を比較する。本実施形態では、両レイヤ内のタスク数は３で同一であるので、空タスクは生成せずに、処理Ｓ１０に進む。
【０１００】
処理Ｓ１０（２週目）において、タスク配置手段２２は、閉包先行関係記憶手段１７に基づいて、レイヤ２内の各タスクに対して、後続となり得るレイヤ３内のタスクの集合を判定する。本実施形態では、まず、タスク４の後続タスク候補としてタスク６、タスク７およびタスク８が判定される。ここで、空タスクの後続候補は、空タスクに先行する空タスク以外のタスクのうち、最も高レイヤのタスクｘが直接または間接の先行関係を有するタスクｙとなる。本実施形態では、空タスク１の後続タスク候補として、空タスクに先行する空タスク以外のタスクのうち、最も高レイヤのタスク２が間接の先行関係を有するタスク６、タスク７およびタスク８が判定される。一方、タスク５の後続タスク候補は存在しない。
【０１０１】
処理Ｓ１１（２週目）において、タスク配置手段２２は、グラフの最大マッチングアルゴリズムを用いて、レイヤ２内の各タスクとその後続タスクについて、最大マッチングを取得する。本実施形態では、組み合わせ１｛［タスク４→タスク６］，［空タスク１→タスク７］｝、組み合わせ２｛［タスク４→タスク７］，［空タスク１→タスク６］｝など、複数の最大マッチングが得られる。
【０１０２】
処理Ｓ１２（２週目）において、タスク配置手段２２は、処理Ｓ１１で得られた最大マッチングのマッチング数２とレイヤ２内のタスク数３を比較する。本実施形態では、マッチング数がタスク数より少ないので、処理Ｓ１３に進む。
【０１０３】
処理Ｓ１３（２週目）において、タスク配置手段２２は、マッチング数とタスク数の差の数、レイヤＬおよびレイヤＬ−１に空タスクを生成し、空タスクを配置するために、新たなレベルの領域を作成する。本実施形態では、レイヤ２およびレイヤ３に空タスク２、空タスク３がそれぞれ生成され、空タスク２を配置するために、レベル４の領域が生成される。図２８は、処理Ｓ１３時点のタスク構造体に配置されたＰＥＲＴ図のイメージ図である。
【０１０４】
処理Ｓ１３後、再度処理Ｓ１０に戻る。処理Ｓ１０（２週目、２度目）において、タスク配置手段２２は、閉包先行関係記憶手段１７に基づいて、レイヤ２内の各タスクに対して、後続となり得るレイヤ３内のタスクの集合を判定する。本実施形態では、タスク４、空タスク１、空タスク２の後続タスク候補として、いずれもタスク６、タスク７、タスク８および空タスク３が、タスク５の後続タスク候補として空タスク３が判定される。
【０１０５】
処理Ｓ１１（２週目、２度目）において、タスク配置手段２２は、グラフの最大マッチングアルゴリズムを用いて、レイヤ２内の各タスクとその後続タスクについて、最大マッチングを取得する。本実施形態では、組み合わせ１｛［タスク４→タスク６］，［空タスク１→タスク７］，［タスク５→空タスク３］，［空タスク２→タスク８］｝、組み合わせ２｛［タスク４→タスク７］，［空タスク１→タスク６］｝など、複数の最大マッチングが得られる。
【０１０６】
処理Ｓ１２（２週目、２度目）において、タスク配置手段２２は、処理Ｓ１１で得られた最大マッチングのマッチング数４とレイヤ２内のタスク数４を比較する。本実施形態では、マッチング数とタスク数とが一致するので、処理Ｓ１４に進む。
【０１０７】
処理Ｓ１４（２週目）において、タスク配置手段２２は、レイヤ３をレイヤ３内に存在するタスク数である４つのレベルに分割し、分割した領域にタスクを配置する。本実施形態では、レイヤ３のレベル１にタスク６を、レイヤ３のレベル２にタスク７を、レイヤ３のレベル３に空タスク３を、レイヤ３のレベル４にタスク８を配置する。図２９は、処理Ｓ１４（２週目）時点のタスク構造体に配置されたＰＥＲＴ図のイメージ図である。
【０１０８】
処理Ｓ１５（２週目）において、イベント識別手段２３は、レイヤ２内のタスクｘの後続としてレイヤ３内に配置できなかったタスクｙを識別し、イベント記憶手段２０に記憶する。本実施形態では、タスク４の後続として配置できなかったタスク７、タスク４の後続として配置できなかったタスク８が識別され、イベント記憶手段２０に記憶される。なお、レイヤ２内のタスク５の後続としてレイヤ３内に配置できなかったタスク９については、ここでは記憶されない。レイヤＬ−１内のタスクｘの後続としてレイヤＬ内に配置できなかったタスクｙが存在する場合であっても、タスクｘの後続として空タスクが配置されている場合には、この空タスクの後続としてタスクｙが配置されないときのみ、イベント記憶手段２０に記憶する。したがって、ここでは、図２１のイベント識別子e2およびe3により識別されるレコードが登録される。
【０１０９】
レイヤ３に対する処理を終え、処理Ｓ１６（２週目）において、タスク配置手段２２は、レイヤＬにレイヤ４をセットし、処理Ｓ８に戻る。
【０１１０】
本実施形態では、処理Ｓ８（３週目）において、タスク配置手段２２は、レイヤＬがフィニッシュ時間に対応するレイヤｔであるか否か判定し、レイヤＬはレイヤ４であるので、処理Ｓ９に進む。
【０１１１】
処理Ｓ９（３週目）において、タスク配置手段２２は、レイヤ４およびレイヤ３内のタスク数を比較する。本実施形態では、レイヤ４内のタスク数が１、レイヤ３内のタスク数が４であるので、レイヤ４に空タスクを３つ生成する。図３０は、処理Ｓ９（３週目）時点のタスク構造体に配置されたＰＥＲＴ図のイメージ図である。
【０１１２】
処理Ｓ１０（３週目）において、タスク配置手段２２は、閉包先行関係記憶手段１７に基づいて、レイヤ３内の各タスクに対して、後続となり得るレイヤ４内のタスクの集合を判定する。本実施形態では、タスク６、タスク７、タスク８、空タスク３の後続タスク候補として、いずれもタスク９、空タスク４、空タスク５および空タスク６が判定される。
【０１１３】
処理Ｓ１１（３週目）において、タスク配置手段２２は、グラフの最大マッチングアルゴリズムを用いて、レイヤ３内の各タスクとその後続タスクについて、最大マッチングを取得する。本実施形態では、組み合わせ１｛［タスク６→空タスク４］，［タスク７→空タスク５］，［空タスク３→タスク９］，［タスク８→空タスク６］｝など、複数の最大マッチングが得られる。
【０１１４】
処理Ｓ１２（３週目）において、タスク配置手段２２は、処理Ｓ１１で得られた最大マッチングのマッチング数４とレイヤ３内のタスク数４を比較する。本実施形態では、マッチング数とタスク数とが一致するので、処理Ｓ１４に進む。
【０１１５】
処理Ｓ１４（３週目）において、タスク配置手段２２は、レイヤ４をレイヤ内に存在するタスク数である４つのレベルに分割し、分割した領域にタスクを配置する。本実施形態では、レイヤ４のレベル１に空タスク４を、レイヤ４のレベル２に空タスク５を、レイヤ４のレベル３にタスク９を、レイヤ４のレベル４に空タスク６を配置する。図３１は、処理Ｓ１４（３週目）時点のタスク構造体に配置されたＰＥＲＴ図のイメージ図である。
【０１１６】
処理Ｓ１５（３週目）において、イベント識別手段２３は、レイヤ３内のタスクｘの後続としてレイヤ４内に配置できなかったタスクｙを識別し、イベント記憶手段２０に記憶する。本実施形態では、タスク６の後続として配置できなかったタスク９、タスク７の後続として配置できなかったタスク９、タスク８の後続として配置できなかったタスク９が識別され、イベント記憶手段２０に記憶される。なお、レイヤ２内のタスク５の後続としてレイヤ３内に配置できなかったタスク９は、レイヤ３の空タスクを介して、レイヤ４内にタスク５の後続として配置されているので、イベント記憶手段２０には記憶されない。したがって、ここでは、図２１のイベント識別子e4、e5およびe6により識別されるレコードが登録される。
【０１１７】
レイヤ４に対する処理を終え、処理Ｓ１６（３週目）において、タスク配置手段２２は、レイヤＬにレイヤｔをセットし、処理Ｓ８に戻る。
【０１１８】
本実施形態では、処理Ｓ８（４週目）において、タスク配置手段２２は、レイヤＬがフィニッシュ時間に対応するレイヤｔであるか否か判定し、レイヤＬはレイヤｔであるので、処理Ｓ１７に進む。
【０１１９】
処理Ｓ１７において、タスク配置手段２２は、上述の処理で得られたタスク配置構造体の情報をタスク配置記憶手段１９に記憶する。
【０１２０】
処理Ｓ１８において、スケジュール変換手段２４は、タスク配置記憶手段１９のタスク配置構造体およびイベント記憶手段２０に基づいて、スケジュールを作成する。
【０１２１】
（スケジュール作成方法−タスク配置構造体からの変換）
次に、図３２のフローチャートを参照して、タスク配置記憶手段１９のタスク配置構造体およびイベント記憶手段２０に基づいて、スケジュールを作成する工程を詳述する。本実施形態では、（スケジュールの作成−並列実行）の章同様、Event Objectを用いるものとする。
【０１２２】
処理Ｓ１において、スケジュール変換手段２４は、スケジュール未作成のレベルが存在するか否か判定する。未作成のレベルが存在する場合、処理Ｓ２に進み、未作成のレベルが存在しない場合には処理を終了する。本実施形態では、未作成のレベルが存在するので、処理Ｓ２に進む。
【０１２３】
処理Ｓ２において、スケジュール変換手段２４は、タスク構造体のレベルのうち、スケジュールを作成していないレベルを抽出し、かつ、レイヤＣにレイヤ１をセットする。本実施形態では、レベル１を抽出するものとする。
【０１２４】
処理Ｓ３において、スケジュール変換手段２４は、レイヤＣがフィニッシュ時間に対応するレイヤｔであるか否か判定する。レイヤｔでない場合、処理Ｓ４に進み、レイヤｔである場合には処理Ｓ１に戻る。本実施形態では、レイヤＣはレイヤ１であるので、処理Ｓ４に進む。
【０１２５】
処理Ｓ４において、スケジュール変換手段２４は、レイヤＣに配置されたタスクを識別する。本実施形態では、レイヤ１に配置されたタスク１を識別する。
【０１２６】
処理Ｓ５において、スケジュール変換手段２４は、イベント記憶手段２０に基づいて、処理Ｓ４で識別したタスクを実行する前に待機すべきイベントが存在するか否かを判定する。待機すべきイベントが存在する場合は処理Ｓ６に進み、存在しない場合には処理Ｓ７に進む。本実施形態では、イベント記憶手段２０の待機タスクに対象となるタスクが格納されているか否かにより判定を行うことができる。ここでは、図２１に示されるように、待機タスクにタスク１が格納されたレコードは存在しないので、処理Ｓ７に進む。処理Ｓ６については後述する。
【０１２７】
処理Ｓ７において、スケジュール変換手段２４は、処理Ｓ４で識別したタスクが空タスクでない場合、当該タスクの実行をスケジュールとして記述する。本実施形態では、タスク１の実行をtask1()と記述する。
【０１２８】
処理Ｓ８において、スケジュール変換手段２４は、イベント記憶手段２０に基づいて、処理Ｓ４で識別したタスクの完了を通知すべきイベントが存在するか否かを判定する。通知すべきイベントが存在する場合は処理Ｓ９に進み、存在しない場合には処理Ｓ１０に進む。本実施形態では、イベント記憶手段２０の通知タスクに対象となるタスクが格納されているか否かにより判定を行うことができる。ここでは、図２１に示されるように、通知タスクにタスク１が格納されたレコードは存在しないので、処理Ｓ１０に進む。処理Ｓ９については後述する。
【０１２９】
処理Ｓ３から処理Ｓ９までが、１つのレイヤに対する処理である。処理Ｓ１０において、スケジュール変換手段２４は、レイヤＣに現在処理中のレイヤの次のレイヤをセットし、処理Ｓ３に戻る。ここでは、レイヤＣにレイヤ２をセットする。
【０１３０】
処理Ｓ３（２週目）において、スケジュール変換手段２４は、レイヤＣがフィニッシュ時間に対応するレイヤｔであるか否か判定し、レイヤＣはレイヤ２であるので、処理Ｓ４に進む。
【０１３１】
処理Ｓ４（２週目）において、スケジュール変換手段２４は、レイヤ２に配置されたタスク４を識別する。処理Ｓ５（２週目）において、スケジュール変換手段２４は、イベント記憶手段２０に基づいて、タスク４を実行する前に待機すべきイベントが存在するか否かを判定する。本実施形態では、図２１に示されるように、タスク４を実行する前に待機すべきイベントが存在するので、処理Ｓ６に進む。
【０１３２】
処理Ｓ６（２週目）において、スケジュール変換手段２４は、待機すべきイベントをスケジュールとして記述する。本実施形態では、e0により特定されるEvent Objectがシグナル状態になるまで待機し続けるために、WaitForSingleObject(e0)の呼び出しを記述する。
【０１３３】
処理Ｓ７（２週目）において、スケジュール変換手段２４は、処理Ｓ４で識別したタスク４の実行をスケジュールとして記述する。本実施形態では、タスク４の実行をtask4()と記述する。処理Ｓ８（２週目）において、スケジュール変換手段２４は、イベント記憶手段２０に基づいて、処理Ｓ４で識別したタスク４の完了を通知すべきイベントが存在するか否かを判定する。本実施形態では、図２１に示されるように、タスク４の完了を通知すべきイベントが存在するので、処理Ｓ９に進む。
【０１３４】
処理Ｓ９（２週目）において、スケジュール変換手段２４は、通知すべきイベントをスケジュールとして記述する。本実施形態では、e2およびe3により特定されるEvent Objectをシグナル状態にするために、SetEvent(e2)およびSetEvent(e3)の呼び出しを記述する。
【０１３５】
処理Ｓ１０において、スケジュール変換手段２４は、レイヤＣにレイヤ３をセットし、処理Ｓ３に戻る。同様に、レイヤ３、レイヤ４に対して処理Ｓ３から処理Ｓ９までの処理を行い、最後に、処理Ｓ１０において、レイヤＣにレイヤｔがセットされると、処理Ｓ３の判定を経て、処理Ｓ１に戻る。ここまでの処理によって、レベル１に対応するスケジュールとして、以下に示すスケジュール６−０が作成される。
【０１３６】
また、同様に、処理Ｓ１からフローチャートに従って処理することにより、レベル２に対応するスケジュールとしてスケジュール６−１、レベル３に対応するスケジュールとしてスケジュール６−２、レベル４に対応するスケジュールとしてスケジュール６−３が得られる。
スケジュール６−０＝task1(); WaitForSingleObject(e0); task4(); SetEvent(e2); 
SetEvent(e3); task6(); SetEvent(e4);
スケジュール６−１＝task2(); SetEvent(e0); WaitForSingleObject(e2); task7(); 
SetEvent(e5);
スケジュール６−２＝task3(); SetEvent(e1); task5(); WaitForSingleObject(e4); 
WaitForSingleObject(e5); WaitForSingleObject(e6); task9();
スケジュール６−３＝WaitForSingleObject(e1); WaitForSingleObject(e3); task8(); 
SetEvent(e6);
【０１３７】
以上の処理により、図９に示されるＰＥＲＴ図で表される複数のタスクを、そのタスク間の先行関係のみに基づいてスケジューリングすることができる。タスクの実行時間に依存しないので、タスクの実行時間が変わっても、スケジュールを再作成する必要はなくなる。
【０１３８】
本発明で導かれるスケジュールは、リソース数の制約がない場合に実行時間が最小となるものであって、いずれの実行環境においても、最小時間での実行を保障することができる。さらに、本発明で導かれるスケジュールにより、実行時間が最小となるスケジュールを実行するための最少リソース数を得ることができる。最少リソース数を知ることにより、不必要なリソースを維持する不利益を回避することができる。
【図１】
0005486034.tif 000003
【図２】
0005486034.tif 000004
【図３】
0005486034.tif 000005
【図４】
0005486034.tif 000006
【図５】
0005486034.tif 000007
【図６】
0005486034.tif 000008
【図７】
0005486034.tif 000009
【図８Ａ】
0005486034.tif 000010
【図８Ｂ】
0005486034.tif 000011
【図９】
0005486034.tif 000012
【図１０】
0005486034.tif 000013
【図１１Ａ】
0005486034.tif 000014
【図１１Ｂ】
0005486034.tif 000015
【図１２】
0005486034.tif 000016
【図１３Ａ】
0005486034.tif 000017
【図１３Ｂ】
0005486034.tif 000018
【図１４】
0005486034.tif 000019
【図１５】
0005486034.tif 000020
【図１６】
0005486034.tif 000021
【図１７】
0005486034.tif 000022
【図１８】
0005486034.tif 000023
【図１９】
0005486034.tif 000024
【図２０】
0005486034.tif 000025
【図２１】
0005486034.tif 000026
【図２２】
0005486034.tif 000027
【図２３】
0005486034.tif 000028
【図２４】
0005486034.tif 000029
【図２５】
0005486034.tif 000030
【図２６】
0005486034.tif 000031
【図２７】
0005486034.tif 000032
【図２８】
0005486034.tif 000033
【図２９】
0005486034.tif 000034
【図３０】
0005486034.tif 000035
【図３１】
0005486034.tif 000036
【図３２】
0005486034.tif 000037