(57)【特許請求の範囲】
【請求項１】
並行プログラムのプログラムエラーの除去を支援するためのプログラミング支援装置において、
複数のプロセスからなる第１の並行プログラムの各プロセスを複数のセクションに区分する区分手段と、
前記第１の並行プログラムにおける前記複数のセクションのあり得る実行順序の集合を表すネットワーク構造を、前記並行プログラムのある状態を表すノードからこの状態に後続し得るプロセスの各セクションがそれぞれ一つの分岐エッジとして次のノードに伸びるように表し、前記ネットワーク構造の一つの経路が一つのあり得る実行順序を示すように生成する生成手段と、
前記ネットワーク構造の各分岐について前記エッジによって表されるセクションに関するユーザの選択結果として選択されたセクションを入力する入力手段と、
前記第１の並行プログラムを、その第１の並行プログラムについて前記選択されたセクションを選択された実行順序で実行する第２の並行プログラムに変換するために、各セクション間に同期命令を挿入する変換手段とを具備することを特徴とするプログラミング支援装置。
【請求項２】
並行プログラムのプログラムエラーの検出を支援するためのプログラミング支援方法において、
入力手段を備えたコンピュータとそれを制御するソフトウェアにより実現される区分手段、生成手段、変換手段を用いて、
前記区分手段により、複数のプロセスからなる第１の並行プログラムの各プロセスを複数の制御可能なセクションに区分する区分処理と、
前記生成手段により、前記各プロセスの前記セクションのあり得る実行順序の全てを、前記セクション間の分岐を用いて表す実行経路を生成する生成処理と、
前記入力手段により、前記生成された実行経路中の分岐についてユーザの選択結果として選択されたセクションを入力する入力処理と、
前記変換手段により、前記第１の並行プログラムを、前記選択されたセクションの分岐からなる前記実行経路に基づいて前記セクションを一定の順序で実行する第２の並行プログラムに変換するために、各セクション間に同期命令を挿入する変換処理とを具備することを特徴とするプログラミング支援方法。
【請求項３】
並行プログラムのプログラムエラーの検出を支援するためのプログラミング支援装置において、
複数のプロセスからなる第１の並行プログラムの各プロセスを複数の制御可能なセクションに区分する区分手段と、
前記各プロセスの前記セクションのあり得る実行順序について実行可能な全ての実行経路を、その実行経路の分岐が前記セクションの実行順序となるように生成する生成手段と、
前記生成手段によって生成された前記実行可能な全ての実行経路中の分岐についてユーザの選択結果として選択されたセクションを入力する入力手段と、
前記第１の並行プログラムを、前記選択されたセクションの分岐について選択されたセクションを有する第２の並行プログラムに変換するために、各セクション間に同期命令を挿入する変換手段とを具備することを特徴とするプログラミング支援装置。
【請求項４】
前記生成手段は、前記各プロセスの前記各セクションの実行順序を、前記選択の結果が前記第２の並行プログラムによる実行結果に影響を与えるセクション間の分岐に限定して表す実行経路を生成するように構成されたことを特徴とする請求項３記載のプログラミング支援装置。
【請求項５】
前記実行経路を、前記選択結果が前記第２の並行プログラムによる実行結果に影響を与えないセクション間の分岐を付加することによって拡張する拡張手段を具備することを特徴とする請求項４記載のプログラミング支援装置。
【請求項６】
並行プログラムのプログラムエラーの検出を支援するためのプログラミング支援装置において、
複数のプロセスからなる第１の並行プログラムの各プロセスを複数の制御可能なセクションに区分する区分手段と、
前記各セクション間の依存関係を検出する検出手段と、
前記各プロセスの前記セクションのあり得る実行順序の全てを、前記セクション間の分岐を用いて表す実行経路を生成する生成手段と、
前記依存関係を有する分岐についてユーザの選択結果として選択されたセクションを入力する入力手段と、
前記第１の並行プログラムを、前記選択されたセクションの分岐からなる前記実行経路に基づいて前記セクションを一定の順序で実行する第２の並行プログラムに変換するために、各セクション間に同期命令を挿入する変換手段とを具備することを特徴とするプログラミング支援装置。
【請求項７】
前記生成手段は、前記各プロセスの前記各セクションの実行順序を、前記依存関係を有するセクション間の分岐に限定して表す実行経路を生成するように構成されたことを特徴とする請求項６記載のプログラミング支援装置。
【請求項８】
前記実行経路を、前記依存関係のないセクション間の分岐を付加することによって拡張する拡張手段を有することを特徴とする請求項７記載のプログラミング支援装置。
【請求項９】
前記第１の並行プログラムを、前記実行経路上のセクション間の実行順序に基づいて模擬実行する実行手段を具備することを特徴とする請求項３または６記載のプログラミング支援装置。
【請求項１０】
前記変換手段は、前記依存関係において実行が先とされた前記セクションの後に、プロセス間の同期を実現するための第１の命令を挿入し、当該依存関係において実行が後とされた前記セクションの前に、前記第１の命令に対応する第２の命令を挿入することによって、前記変換を行うように構成されたことを特徴とする請求項３または６記載のプログラミング支援装置。
【請求項１１】
前記拡張手段は、
前記実行経路を前記各プロセスに対応させて分解し前記プロセス毎の実行経路を生成する分解手段と、
前記プロセス毎の実行経路について、冗長な部分を削除する削除手段とを有し、
前記変換手段は、前記冗長な部分が削除された各実行経路に基づいて、前記第２の並行プログラムを生成するように構成されたことを特徴とする請求項５または８記載のプログラミング支援装置。
【請求項１２】
前記拡張手段は、
前記実行経路を前記各プロセスに対応させて分解し前記プロセス毎の実行経路を生成する分解手段と、
前記プロセス毎の実行経路について、冗長な部分を削除する削除手段とを有し、
前記変換手段は、前記冗長な部分が削除された各実行経路に基づいて、前記第２の並行プログラムを生成するように構成され、
前記分解手段は、前記実行経路を分解する際に、前記各実行経路に対し該実行経路間の同期をとるための同期命令を付加するように構成され、
前記削除手段は、前記同期命令のうち冗長な同期命令を除去するように構成されたことを特徴とする請求項５または８記載のプログラミング支援装置。
【請求項１３】
並行プログラムのプログラムエラーの検出を支援するためのプログラミング支援装置において、
複数のプロセスからなる第１の並行プログラムの各プロセスが、それぞれ複数のセクションからなる場合に、前記複数のセクションのあり得る実行順序の全てを、前記セクション間の分岐を用いて表す実行経路を生成する生成手段と、
前記第１の並行プログラムを、前記生成手段によって生成された前記実行経路に基づいて前記セクションを一定の順序で実行する第２の並行プログラムに変換するために、各セクション間に同期命令を挿入する変換手段と、
依存関係のないセクション間の分岐を付加することによって前記実行経路を拡張する拡張手段とを具備し、
前記拡張手段は、
前記実行経路を前記各プロセスに対応させて分解し前記プロセス毎の実行経路を生成する分解手段と、
前記プロセス毎の実行経路について、冗長な部分を削除する削除手段とを有し、
前記変換手段は、前記冗長な部分が削除された各実行経路に基づいて、前記第２の並行プログラムを生成するように構成されたことを特徴とするプログラミング支援装置。
【請求項１４】
前記分解手段は、前記実行経路を分解する際に、前記各実行経路に対し該実行経路間の同期をとるための同期命令を付加するように構成され、
前記削除手段は、前記同期命令のうち冗長な同期命令を除去するように構成されたことを特徴とする請求項１３記載のプログラミング支援装置。
【請求項１５】
並行プログラムのプログラムエラーの検出を支援するためのプログラミング支援方法において、
入力手段を備えたコンピュータとそれを制御するソフトウェアにより実現される区分手段、検出手段、生成手段、変換手段を用いて、
前記区分手段により、複数のプロセスからなる第１の並行プログラムの各プロセスを複数の制御可能なセクションに区分する区分処理と、
前記検出手段により、前記各セクション間の依存関係を検出する検出処理と、
前記生成手段により、前記各プロセスの前記セクションのあり得る実行順序の全てを、前記セクション間の分岐を用いて表す実行経路を生成する生成処理と、
前記入力手段により、前記依存関係を有する分岐についてユーザの選択結果として選択されたセクションを入力する入力処理と、
前記変換手段により、前記第１の並行プログラムを、前記選択されたセクションの分岐からなる前記実行経路に基づいて前記セクションを一定の順序で実行する第２の並行プログラムに変換するために、各セクション間に同期命令を挿入する変換処理とを具備することを特徴とするプログラミング支援方法。
【請求項１６】
並行プログラムのプログラムエラーの検出を支援するためのプログラミング支援方法において、
コンピュータとそれを制御するソフトウェアにより実現される生成手段、変換手段、拡張手段を用いて、
前記生成手段により、複数のプロセスからなる第１の並行プログラムの各プロセスが、それぞれ複数のセクションからなる場合に、前記複数のセクションのあり得る実行順序の全てを、前記セクション間の分岐を用いて表す実行経路を生成する生成処理と、
前記変換手段により、前記第１の並行プログラムを、前記生成処理によって生成された前記実行経路に基づいて前記セクションを一定の順序で実行する第２の並行プログラムに変換するために、各セクション間に同期命令を挿入する変換処理と、
前記拡張手段により、依存関係のないセクション間の分岐を付加することによって前記実行経路を拡張する拡張処理とを具備し、
前記拡張処理は、
前記実行経路を前記各プロセスに対応させて分解し前記プロセス毎の実行経路を生成する分解処理と、
前記プロセス毎の実行経路について、冗長な部分を削除する削除処理とを有し、
前記変換処理は、前記冗長な部分が削除された各実行経路に基づいて、前記第２の並行プログラムを生成することを特徴とするプログラミング支援方法。
【発明の詳細な説明】
【０００１】
【発明の属する技術分野】
本発明は、プログラミングを支援するプログラミング支援装置及びプログラミング支援方法の改良に関するもので、特に、信頼性の高い並行プログラムを容易に開発するものに係る。
【０００２】
【従来の技術】
近年、半導体集積回路技術の進歩により、複雑なプロセッサ及び大容量のメモリが小型かつ低価格で実現できるようになり、多数のプロセッサからなる並行処理システムや分散処理システムが実用化されている。このようなハードウエアに対しては、専用のプログラム、すなわち並列プログラムや分散処理プログラム等（以下「並行プログラム(Concurrent Program=CP) 」という）を用いなければならない。
【０００３】
この並行プログラムは、複数のプロセスが同時並行的に動作するプログラムであって、その一類型は、複数のＣＰＵを有する並列計算機上で、複数のプログラムが物理的に並行に動くプログラムである。また、単一のＣＰＵ上で物理的には逐次的に動作する場合でも、マルチタスクシステムのように複数のプロセスが論理的に並行に動作するプログラムは、並行プログラムに含まれる。なお、このように物理的または論理的な並行性を持つシステムを並行システムと呼び、並行システムでは一般に並行プログラムが動作する。このような並行プログラムをいかに効率よく開発するかは、優れたアルゴリズムを検討する場合と同様に重要な課題となっている。
【０００４】
ところで、プログラム開発においては、プログラム中のバグを見付け修正すること（すなわち、テスト・デバッグ）と呼ばれる開発工程がプログラム開発の効率に大きく影響する。しかし、並行プログラムの開発においては、逐次プログラムの開発においては遭遇することのない、並行プログラム特有の問題を考慮する必要がある。この並行プログラム特有の問題とは、並行プログラムを構成する各プロセスは、各プロセス間における相互作用のタイミングによる様々な振る舞いをする可能性があるため、並行プログラム全体が正しく動作しないという問題である。この問題は、並行プログラムの性質に基づく問題であり、一般に「非決定性（nondeterminism）」と呼ばれる。
【０００５】
非決定性は、よい非決定性、悪い非決定性、無害の非決定性に分けられる。このうち、よい非決定性は、（プログラムの）設計者の実現したい非決定性であり、この非決定性により、外部（環境）からの非決定的な刺激に適切に反応でき、プロセスの柔軟性、再利用性、拡張性を実現できる。
【０００６】
一方、悪い非決定性は、設計者が予想ないし期待しない非決定性であり、しばしばプログラムの機能不全を生じさせる。すなわち、人間の一般的思考形態は逐次であり、設計者が逐次的に思考した場面が、並行プログラムの複数のプロセス間で実際に生じ得る場面のすべてを網羅することは困難である。このため、設計時には予想しなかったケースが、実際の並行プログラムの実行では多々発生する。
【０００７】
無害の非決定性は、非決定的な選択子の選択が、実行効率には影響があっても、最終的に得られる結果には悪影響を与えない場合の非決定性である。
【０００８】
以下、上記悪い非決定性について示す。例えば、図３３に示す並行プログラムを考慮する。図３３（ａ）において、プロセスＰ１は、共有メモリＭの初期設定（ｉｎｉｔ）を行うプロセス、プロセスＰ２は、共有メモリＭから読み出し（ｒｅａｄ）を行うプロセス、プロセスＰ３は、共有メモリＭに書込み（ｗｒｉｔｅ）を行うプロセスを示す。これらのプロセスをそれぞれ異なるプロセッサで実行するような並行処理システム等で動作させた場合、図３３（ｂ）に示すように、全部で６通りの動作の組み合わせがあることになる。通常、システムは初期設定で処理を開始するため、今、プロセスＰ１（ｉｎｉｔ）→Ｐ２（ｒｅａｄ）→Ｐ３（ｗｒｉｔｅ）又はＰ１（ｉｎｉｔ）→Ｐ３（ｗｒｉｔｅ）→Ｐ２（ｒｅａｄ）の順番でプログラムが動作する場合に正しい結果が得られるものとすれば、残りの４通り（例えばＰ２→Ｐ３→Ｐ１）は、初期化が最初に行われないため、明らかに正しい結果が得られないことがわかる。
【０００９】
上記のようにプロセスの振る舞いに関する非決定性は、並行プログラムを動作させる毎に、その時点におけるシステムの状況等によって結果が異なったものになる。従って、この非決定性に関する問題を解決しない限り、その並行プログラムは、テストにおいてたとえ正常に動作することがあっても、常に正常に動作するという保証はない。
【００１０】
また、非決定性に関するバグは、一般に、逐次プログラムにおけるバグを見付ける場合よりも困難である。なぜなら、逐次プログラムにおいては、テスト・デバッグ時にプログラム中の全てのパスを実行することによって動作を確認することができるのに対し、並行プログラムにおいては、全ての組合せ的なパス（すなわわち、各プロセス中の全てのパスのみならず、プロセス相互間の振る舞い）を考慮してパスを実行しなければならないからである。上記の例のようにプロセスの数が少ない場合にあっては、各プロセス相互間の振る舞いを全て列挙することは比較的容易であるが、実際のプログラム開発では、その数は膨大になり、その組合わせも膨大なものとなるため、全ての振る舞いを把握することはもはや不可能なものとなる。
【００１１】
【発明が解決しようとする課題】
ところで、一般に、プログラミングには、従来からプログラミング支援装置及びこのプログラミング支援装置上で実行されるプログラミング支援方法が用いられている。プログラミング支援装置及びプログラミング支援方法は、開発ツールと俗称され、一般的にエディタ、デバッガ、プリプロセッサ、オプティマイザ、解析ツール、シミュレータ、コンパイラ、リンカなどを含む。
【００１２】
従来のプログラミング支援装置及びプログラミング支援方法におけるプログラミングの手順の典型例は、あり得る入出力をテストケースとして表し、テストケースによってプログラムをテスト実行し、バグを発見するとテストの結果を参照しながらソースコードの修正を行うことであった。また、従来技術では、解析ツールによってソースコードやデータの構造を解析し、コンパイラが、この解析結果を利用しながら実行効率やメモリ効率の優れた実行コードを生成するなども可能であった。
【００１３】
しかしながら、並行プログラムは、プログラムを構成する複数のプロセスの実行のタイミングによって挙動が非決定的に変化するので、まず、あり得るテストケースの数が組合せ的な爆発を示すことが一般的である。また、タイミングに係わるバグには再現性が無く、テストケース自体の作成も困難であった。
【００１４】
さらに、従来のプログラミング支援装置及びプログラミング支援方法では、解析やテスト実行の結果をプログラムに反映させるにあたって、このような並行プログラムの特徴は考慮されていなかった。このため、従来のプログラミング支援装置やプログラミング支援方法では、信頼性の高い並行プログラムを開発することが困難であった。
【００１５】
なお、並行プログラムの開発（並行プログラミング）を改良したものとして、超逐次プログラミング(Hyper Sequential Programming)が知られている（参考文献：特開平８−１６４２９号）。超逐次プログラミングは、並行プログラムを一旦逐次化して超逐次プログラムを生成し、この超逐次プログラムに対してプログラミング、テスト・デバッグを行う。これは、従来の逐次プログラミングと同じレベルの困難さであり、通常の並行プログラミングの困難さよりはるかに少ない。そして、テスト・デバッグが完了した時点で、テスト・デバッグ情報を用いて上記超逐次プログラムを並行性し、並行プログラムを復元する。
【００１６】
このような超逐次プログラミングでは、悪い非決定性をもたらす要素間に、逐次実行を実現する制御を与えて悪い非決定性を抑制する一方で、無害の非決定性やよい非決定性を残し、並行プログラムの柔軟性という利点を享受することができる。
【００１７】
しかしながら、並行プログラムを逐次化して一旦超逐次プログラムを生成し、それから再び並行プログラムを復元するという作業が必要であり、信頼性の高い並行プログラムを容易に作成することができなかった。また、無害の非決定性についての設計者の処理を省略すること等によってプログラミングを効率化したり、無害の非決定性を容易に取り込むこと等により、プログラミングの信頼性とプログラミングの効率とを向上させることは容易ではなかった。
【００１８】
本発明は、上記のような従来技術の問題点を解決するためのもので、その目的は、プロセスの各セクションのあり得る実行順序を表す実行経路に基づいてプログラムを生成することにより、信頼性の高い並行プログラムを容易に開発するプログラミング支援装置及びプログラミング支援方法を提供することである。また、本発明の他の目的は、設計者の処理を省略したり、無害の非決定性を容易に取り込むことにより、プログラミングの効率を向上させるプログラミング支援装置及びプログラミング支援方法を提供することである。更に、本発明の他の目的は、実行経路に基づいて並行性を復元することにより効率よく並行プログラムを生成することができるプログラミング支援装置及びプログラミング支援方法を提供することである。
【００１９】
また、本発明は、上述した超逐次プログラミングにおいて並行プログラムを逐次化する部分、及び並行プログラムを復元する部分のアルゴリズムを改善したものである。
【００２０】
【課題を解決するための手段】
上記の目的を達成するため、請求項１記載の発明は、並行プログラムのプログラムエラーの除去を支援するためのプログラミング支援装置において、複数のプロセスからなる第１の並行プログラムの各プロセスを複数のセクションに区分する区分手段と、前記第１の並行プログラムにおける前記複数のセクションのあり得る実行順序の集合を表すネットワーク構造を、前記並行プログラムのある状態を表すノードからこの状態に後続し得るプロセスの各セクションがそれぞれ一つの分岐エッジとして次のノードに伸びるように表し、前記ネットワーク構造の一つの経路が一つのあり得る実行順序を示すように生成する生成手段と、前記ネットワーク構造の各分岐について前記エッジによって表されるセクションに関するユーザの選択結果として選択されたセクションを入力する入力手段と、前記第１の並行プログラムを、その第１の並行プログラムについて前記選択されたセクションを選択された実行順序で実行する第２の並行プログラムに変換するために、各セクション間に同期命令を挿入する変換手段とを具備することを特徴としている。
【００２１】
請求項２記載の発明は、並行プログラムのプログラムエラーの検出を支援するためのプログラミング支援方法において、入力手段を備えたコンピュータとそれを制御するソフトウェアにより実現される区分手段、生成手段、変換手段を用いて、前記区分手段により、複数のプロセスからなる第１の並行プログラムの各プロセスを複数の制御可能なセクションに区分する区分処理と、前記生成手段により、前記各プロセスの前記セクションのあり得る実行順序の全てを、前記セクション間の分岐を用いて表す実行経路を生成する生成処理と、前記入力手段により、前記生成された実行経路中の分岐についてユーザの選択結果として選択されたセクションを入力する入力処理と、前記変換手段により、前記第１の並行プログラムを、前記選択されたセクションの分岐からなる前記実行経路に基づいて前記セクションを一定の順序で実行する第２の並行プログラムに変換するために、各セクション間に同期命令を挿入する変換処理とを具備することを特徴としている。
【００２２】
請求項３記載の発明は、並行プログラムのプログラムエラーの検出を支援するためのプログラミング支援装置において、複数のプロセスからなる第１の並行プログラムの各プロセスを複数の制御可能なセクションに区分する区分手段と、前記各プロセスの前記セクションのあり得る実行順序について実行可能な全ての実行経路を、その実行経路の分岐が前記セクションの実行順序となるように生成する生成手段と、前記生成手段によって生成された前記実行可能な全ての実行経路中の分岐についてユーザの選択結果として選択されたセクションを入力する入力手段と、前記第１の並行プログラムを、前記選択されたセクションの分岐について選択されたセクションを有する第２の並行プログラムに変換するために、各セクション間に同期命令を挿入する変換手段とを具備することを特徴としている。
【００２３】
請求項１〜３記載の発明によれば、第１の並行プログラムの複数のプロセスが実行制御可能なセクションに区分され、各セクションのあり得る実行順序が実行経路（シナリオ）で表される。シナリオは、例えばネットワーク構造の状態遷移図で表すことができ、ある状態を表すノードからは、この状態に後続して実行可能な各セクションが、分岐エッジとして次の状態のノードに伸びる。このようなシナリオ上には、各セクションのあり得る実行順序に対応して、順序と同数の経路が存在する。このシナリオの各分岐について、先に実行すべきセクションのエッジを選択していくことにより、意図する実行順序の組み合わせからなるシナリオが生成される。このシナリオに基づいて、第１の並行プログラムを変換して生成された第２の並行プログラムは、悪い非決定性が存在しない。このように、請求項１記載の発明によれば、シナリオ上で実行順序を指定するだけで指定通りの挙動を示すプログラムを得ることができるため、信頼性の高い並行プログラムを容易に作成することができる。
【００２４】
請求項４記載の発明は、請求項３記載のプログラミング支援装置において、前記生成手段は、前記各プロセスの前記各セクションの実行順序を、前記選択の結果が前記第２の並行プログラムによる実行結果に影響を与えるセクション間の分岐に限定して表す実行経路を生成するように構成されたことを特徴としている。
【００２５】
請求項４記載の発明によれば、選択の結果が第２の並行プログラムによる実行結果に影響を与えない、すなわち、悪い非決定性を生じないセクション間の分岐が実行経路（シナリオ）に含まれないため、シナリオが単純化され理解容易となり、プログラミングが効率化される。
【００２６】
請求項５記載の発明は、請求項４記載のプログラミング支援装置において、前記実行経路を、前記選択結果が前記第２の並行プログラムによる実行結果に影響を与えないセクション間の分岐を付加することによって拡張する拡張手段を具備することを特徴としている。
【００２７】
請求項５記載の発明によれば、選択の結果が第２の並行プログラムによる実行結果に影響を与えない分岐、すなわち、無害な非決定性を生じる分岐が付加されるため、変換後の第２の並行プログラムの非決定性が増大し、プログラムの並列性が高まり性能と柔軟性が向上する。
【００２８】
請求項６記載の発明は、並行プログラムのプログラムエラーの検出を支援するためのプログラミング支援装置において、複数のプロセスからなる第１の並行プログラムの各プロセスを複数の制御可能なセクションに区分する区分手段と、前記各セクション間の依存関係を検出する検出手段と、前記各プロセスの前記セクションのあり得る実行順序の全てを、前記セクション間の分岐を用いて表す実行経路を生成する生成手段と、前記依存関係を有する分岐についてユーザの選択結果として選択されたセクションを入力する入力手段と、前記第１の並行プログラムを、前記選択されたセクションの分岐からなる前記実行経路に基づいて前記セクションを一定の順序で実行する第２の並行プログラムに変換するために、各セクション間に同期命令を挿入する変換手段とを具備することを特徴としている。
【００２９】
請求項１５記載の発明は、請求項６記載の発明を方法の観点から把握したものであって、並行プログラムのプログラムエラーの検出を支援するためのプログラミング支援方法において、入力手段を備えたコンピュータとそれを制御するソフトウェアにより実現される区分手段、検出手段、生成手段、変換手段を用いて、前記区分手段により、複数のプロセスからなる第１の並行プログラムの各プロセスを複数の制御可能なセクションに区分する区分処理と、前記検出手段により、前記各セクション間の依存関係を検出する検出処理と、前記生成手段により、前記各プロセスの前記セクションのあり得る実行順序の全てを、前記セクション間の分岐を用いて表す実行経路を生成する生成処理と、前記入力手段により、前記依存関係を有する分岐についてユーザの選択結果として選択されたセクションを入力する入力処理と、前記変換手段により、前記第１の並行プログラムを、前記選択されたセクションの分岐からなる前記実行経路に基づいて前記セクションを一定の順序で実行する第２の並行プログラムに変換するために、各セクション間に同期命令を挿入する変換処理とを具備することを特徴としている。
【００３０】
請求項６、１５記載の発明によれば、第１の並行プログラムの各プロセスが実行制御可能なセクションに区分され、各プロセスの各セクションのあり得る実行順序が実行経路（シナリオ）で表される。このシナリオの各分岐のうち、依存関係を有する分岐においてセクションが選択されることにより、例えば先に実行すべきセクションが選択されていく。これにより、意図する実行順序の組み合わせのみからなるシナリオが生成され得る。このシナリオに基づいて、第１の並行プログラムに実行タイミング制御の命令等を挿入して第２の並行プログラムとすることにより、悪い非決定性が存在しない第２の並行プログラムが生成され得る。このように、請求項６、１５記載の発明では、シナリオ上でセクションを選択することにより実行順序を指定するだけで、指定通りの挙動を示すプログラムが得られる。そのため、信頼性の高い並行プログラムを容易に作成することができる。
【００３１】
請求項７記載の発明は、請求項６記載のプログラミング支援装置において、前記生成手段は、前記各プロセスの前記各セクションの実行順序を、前記依存関係を有するセクション間の分岐に限定して表す実行経路を生成するように構成されたことを特徴としている。
【００３２】
請求項７記載の発明によれば、依存関係のないセクション間の分岐が実行経路（シナリオ）に含まれないため、シナリオが単純化され理解容易となり、プログラミングが効率化される。この場合、依存関係を有しないセクション同士の実行順序は悪い非決定性を生じないため、シナリオに含まれない場合でもプログラムの信頼性は低下しない。
【００３３】
請求項８記載の発明は、請求項７記載のプログラミング支援装置において、前記実行経路を、前記依存関係のないセクション間の分岐を付加することによって拡張する拡張手段を有することを特徴としている。
【００３４】
請求項８記載の発明によれば、依存関係のないセクション間の分岐が実行経路（シナリオ）に付加されるが、このような分岐は無害な非決定性を生じる。このため、変換後の第２の並行プログラムの非決定性が増大し、プログラムの並列性が高まり性能と柔軟性が向上する。
【００３５】
請求項９記載の発明は、請求項３または６記載のプログラミング支援装置において、前記第１の並行プログラムを、前記実行経路上のセクション間の実行順序に基づいて模擬実行する実行手段を具備することを特徴としている。
【００３６】
請求項９記載の発明によれば、実行経路（シナリオ）上でセクションを選択する作業が行われる度に、その時点でのシナリオ通りに第１の並行プログラムを模擬実行することができる。このため、実行結果によって選択内容の妥当性を確認したり、プログラム中のバグを発見することによって、並行プログラムの信頼性とプログラミングの効率が向上する。
【００３７】
請求項１０記載の発明は、請求項３または６記載のプログラミング支援装置において、前記変換手段が、前記依存関係において実行が先とされた前記セクションの後に、プロセス間の同期を実現するための第１の命令を挿入し、当該依存関係において実行が後とされた前記セクションの前に、前記第１の命令に対応する第２の命令を挿入することによって、前記変換を行うように構成されたことを特徴としている。
【００３８】
請求項１０記載の発明によれば、セクション間の指定された先行制御が、プロセス間の同期信号によって容易かつ確実に実現される。
【００３９】
請求項１１記載の発明は、請求項５または８記載のプログラミング支援装置において、前記拡張手段が、前記実行経路を前記各プロセスに対応させて分解し前記プロセス毎の実行経路を生成する分解手段と、前記プロセス毎の実行経路について、冗長な部分を削除する削除手段とを有し、前記変換手段が、前記冗長な部分が削除された各実行経路に基づいて、前記第２の並行プログラムを生成するように構成されたことを特徴としている。
【００４０】
請求項１１記載の発明によれば、実行経路（シナリオ）が各プロセスに対応して分解され、プロセス毎のシナリオが生成される。このプロセス毎のシナリオについて、冗長な部分が削除されることにより最適化され、最適化された各シナリオに基づいて第２の並行プログラムが生成される。このように、プロセス毎にシナリオを最適化することにより無害な非決定性を導入することができ、容易に第２の並行プログラムを生成することができる。
【００４１】
請求項１２記載の発明は、請求項５または８記載のプログラミング支援装置において、前記拡張手段が、前記実行経路を前記各プロセスに対応させて分解し前記プロセス毎の実行経路を生成する分解手段と、前記プロセス毎の実行経路について、冗長な部分を削除する削除手段とを有し、前記変換手段が、前記冗長な部分が削除された各実行経路に基づいて、前記第２の並行プログラムを生成するように構成され、前記分解手段が、前記実行経路を分解する際に、前記各実行経路に対し該実行経路間の同期をとるための同期命令を付加するように構成され、前記削除手段が、前記同期命令のうち冗長な同期命令を除去するように構成されたことを特徴としている。
【００４２】
請求項１２記載の発明によれば、実行経路（シナリオ）が各プロセスに対応して分解され、プロセス毎のシナリオが生成される。このとき、分解された個々のシナリオの集合から最初のシナリオが再現できるように、各シナリオに対しシナリオ間の同期をとるための同期制約が付加される。また、このプロセス毎のシナリオについて、冗長な部分、すなわち冗長な同期制約が除去されることにより、最適化される。この最適化により、無害な非決定性が導入される。このように、プロセス毎にシナリオを最適化することにより無害な非決定性を導入することができ、容易に第２の並行プログラムを生成することができる。
【００４３】
請求項１３記載の発明は、並行プログラムのプログラムエラーの検出を支援するためのプログラミング支援装置において、複数のプロセスからなる第１の並行プログラムの各プロセスが、それぞれ複数のセクションからなる場合に、前記複数のセクションのあり得る実行順序の全てを、前記セクション間の分岐を用いて表す実行経路を生成する生成手段と、前記第１の並行プログラムを、前記生成手段によって生成された前記実行経路に基づいて前記セクションを一定の順序で実行する第２の並行プログラムに変換するために、各セクション間に同期命令を挿入する変換手段と、依存関係のないセクション間の分岐を付加することによって前記実行経路を拡張する拡張手段とを具備し、前記拡張手段は、前記実行経路を前記各プロセスに対応させて分解し前記プロセス毎の実行経路を生成する分解手段と、前記プロセス毎の実行経路について、冗長な部分を削除する削除手段とを有し、前記変換手段は、前記冗長な部分が削除された各実行経路に基づいて、前記第２の並行プログラムを生成するように構成されたことを特徴としている。
【００４４】
請求項１６記載の発明は、請求項１３記載の発明を方法の観点から把握したものであって、並行プログラムのプログラムエラーの検出を支援するためのプログラミング支援方法において、コンピュータとそれを制御するソフトウェアにより実現される生成手段、変換手段、拡張手段を用いて、前記生成手段により、複数のプロセスからなる第１の並行プログラムの各プロセスが、それぞれ複数のセクションからなる場合に、前記複数のセクションのあり得る実行順序の全てを、前記セクション間の分岐を用いて表す実行経路を生成する生成処理と、前記変換手段により、前記第１の並行プログラムを、前記生成処理によって生成された前記実行経路に基づいて前記セクションを一定の順序で実行する第２の並行プログラムに変換するために、各セクション間に同期命令を挿入する変換処理と、前記拡張手段により、依存関係のないセクション間の分岐を付加することによって前記実行経路を拡張する拡張処理とを具備し、前記拡張処理は、前記実行経路を前記各プロセスに対応させて分解し前記プロセス毎の実行経路を生成する分解処理と、前記プロセス毎の実行経路について、冗長な部分を削除する削除処理とを有し、前記変換処理は、前記冗長な部分が削除された各実行経路に基づいて、前記第２の並行プログラムを生成することを特徴としている。
【００４５】
請求項１３、１６記載の発明によれば、プロセスが複数のセクションで表され、これら複数のセクションのあり得る実行順序がセクション間の分岐を用いて表された実行経路（シナリオ）が生成される。そして、このシナリオが各プロセスに対応して分解され、プロセス毎のシナリオが生成される。このプロセス毎のシナリオについて、冗長な部分が削除されることにより最適化され、最適化された各シナリオに基づいて第２の並行プログラムが生成される。このように、プロセス毎にシナリオを最適化することにより無害な非決定性を導入することができ、容易に第２の並行プログラムを生成することができる。
【００４６】
請求項１４記載の発明によるプログラミング支援装置は、請求項１３記載の発明において、前記分解手段が、前記実行経路を分解する際に、前記各実行経路に対し該実行経路間の同期をとるための同期命令を付加するように構成され、前記削除手段が、前記同期命令のうち冗長な同期命令を除去するように構成されたことを特徴としている。
【００４７】
請求項１４記載の発明によれば、実行経路（シナリオ）が各プロセスに対応して分解され、プロセス毎のシナリオが生成される。このとき、分解された個々のシナリオの集合から最初のシナリオが再現できるように、各シナリオに対しシナリオ間の同期をとるための同期制約が付加される。また、このプロセス毎のシナリオについて、冗長な部分、すなわち冗長な同期制約が除去されることにより、最適化される。この最適化により、無害な非決定性が導入される。このように、プロセス毎にシナリオを最適化することにより無害な非決定性を導入することができ、容易に第２の並行プログラムを生成することができる。
【００４８】
【発明の実施の形態】
次に、本発明の実施の形態の例について図面にしたがって具体的に説明する。なお、実施の形態の各機能は、所定のソフトウェアがコンピュータ及び周辺機器を制御することで実現される。すなわち、本明細書では、発明及び実施の形態を、各機能や各処理に対応する仮想的回路ブロック（「〜手段」や「〜部」など）を想定して説明している。このため、各ブロックに対して、各ハードウェア要素やソフトウェア要素は１対１には対応しない。
【００４９】
ここで、本発明の実施の形態では、並行プログラムの開発にあたり、並行プログラムを実行するためのいわゆるターゲットマシンを、並行プログラムを開発するためのいわゆるホストマシンとして用いるものとする。
【００５０】
また、本形態では、複数のＣＰＵを用いるいわゆるマルチＣＰＵシステムを用い、各プロセスは共有メモリにアクセスするものとする。図１は、本発明の実施の形態に用いるコンピュータの概念図を示す。すなわち、このコンピュータでは、各プロセッサＣ１，Ｃ２はそれぞれ、プログラムを構成するプロセスＰ１とＰ２を同時並行的に実行し、各プロセッサＣ１，Ｃ２は、プロセスＰ１，Ｐ２の内容に応じて、バス及び入出力制御回路Ｂを経由して、共有メモリＭの他、入力装置Ｉ、出力装置Ｏ、外部記憶装置Ｓなどの周辺装置にアクセスする。
【００５１】
このコンピュータにおいて、典型的には、入力装置Ｉはキーボードやマウスなどであり、各種コマンドやデータの入力を行う手段である。外部記憶装置Ｓは、ハードディスク装置、磁気ディスク又は光磁気ディスクなどからなり、ソースプログラムやデバッグ状況に関する情報を書込み又は読み出すことができるようになっている。出力装置Ｏは、ＣＲＴ表示装置やプリンタ印字装置などであり、ソースプログラムやデバッグ状況に関する情報等をテキスト又はグラフィック表示等することによりユーザに提供する。ユーザは、これら入力装置Ｉ及び出力装置Ｏを用いて、対話的にコンピュータを操作することができる。但し、コンピュータの規模・構成やＣＰＵの数・形式は自由で、例えば、コンピュータネットワーク、分散処理など各種の構成を自由に用い得る。
【００５２】
すなわち、本発明における並行プログラムをターゲットマシンとして実行するコンピュータは、いわゆる並列計算機でもよく、この場合共有メモリの有無は問わない。また、分散ネットワーク計算機システムや単一のＣＰＵにおけるマルチタスクシステムでもよい。なお、単一のＣＰＵにおけるマルチタスクシステムの場合は、１つのＣＰＵに複数のプロセスが存在しうる。
【００５３】
また、本発明におけるホストマシンは、ターゲットマシンと異なってもよく（クロス開発環境）、プログラムのシミュレータを有すれば、単一のＣＰＵのみを有するコンピュータでもよい。
【００５４】
［１．構成］
本実施の形態は、請求項１〜１６に記載のプログラミング支援装置とその方法に対応するものである。
【００５５】
本実施の形態は、図１に示したコンピュータ上で実現されるが、態様の一例は、プロセッサＣ１又はＣ２上で、本実施の形態の各機能を実現するための単一のプロセスからなるプログラムを実行することである。
【００５６】
図２は、本形態の構成を概念的に示す機能ブロック図である。この図に示すように、本装置は、エディタ１、区分手段２、検出手段３、生成手段４、表示手段５、選択手段６、実行手段７、拡張手段８、及び変換手段９を有する。
【００５７】
エディタ１は、コンピュータ上で実行される複数のプロセスを含む第１のプログラムを作成・編集するための手段である。区分手段２は、第１のプログラムの各プロセスを実行制御可能なセクションに区分する。この区分は、例えば、第１のプログラムを構成する各プロセスに、割り込み可能なポイント（以下、「シナリオポイント」という）を設定することによって行う。
【００５８】
検出手段３は、異なったプロセス間において、各セクション間の依存関係（先行制約）を検出する。検出は、例えば以下のように行う。すなわち、あるプロセスにある対象を変更する命令が検出された場合、他の全てのプロセスにおいて、上記命令と同一の対象の状態によって結果が影響される全ての命令を検出する。そして、上記変更する命令について、影響される全ての命令との間に、依存関係が存在するとみなす。
【００５９】
このような場合の依存関係の典型例は、共有メモリの書き込み命令と読み出し命令である。依存関係の他の例は、プロセス間で共有されるフラグを変更する命令と、このフラグに応じて条件判断を行う命令である。逆に、メモリの読み出し命令相互間には依存関係は存在しない場合が一般的と考えられる。また、プロセッサ固有のローカルなメモリのみを処理対象とするサブルーチンは、依存関係検出の対象から除外してよい。
【００６０】
生成手段４は、各プロセスの各セクションのありうる実行順序を、セクション間の分岐を用いて表す実行経路（シナリオ）を生成する。シナリオは、並行プログラムについて無限に存在するテストケースの中で、設計者が期待する挙動を表現した本質的なものであり、また、外部との入出力だけでなく、内部の挙動も表現している点で従来技術のテストケースと異なる。すなわち、並行プログラムにおいては、各命令の実行の先後関係に基づいて極めて多数の経路が存在する。そして、すべてのケースのテストは現実的に困難である一方、本質的に意味のある経路は全経路のごく一部である。なお、このシナリオの表現方法は、例えば文献"Structural Testing of Concurrent Programs "(Richard N. Taylor et al,IEEE TRANSACTIONS ON SOFTWARE ENGINEERING, VOL. 18, NO.3, MARCH 1992) に示されているような周知の方法が採用される。
【００６１】
このようなシナリオは、例えばネットワーク構造の状態遷移図で表すことができる。状態遷移図では、ある状態を表すノードからは、この状態に後続し得るプロセスの各セクションが、分岐エッジとして次の状態のノードに伸びる。
【００６２】
シナリオはツリー構造図で表すこともできるが、同じいくつかの命令が異なった順序で実行された後の経路は合流させても、命令の組み合わせからなる経路の数は減少しない。例えば、ツリー構造において、命令ａ，ｂ，ｃにつき、ａ→ｂ→ｃという順序で実行する枝とｂ→ａ→ｃという順序で実行する枝とに分れている場合に、それらを実行した後の経路を合流させたとしても、全体の経路の数は変わらない。このため、シナリオとしては、ネットワーク構造の方が理解が容易である。すなわち、これらシナリオ上には、各プロセスの各セクションのあり得る実行順序に対応して、順序と同数の経路が存在するためである。
【００６３】
表示手段５は、第１のプログラム及びシナリオ等の各種データを表示する。すなわち、生成手段４によって生成されたシナリオがこの表示手段５に表示される。なお、各種情報を、プリンタなど所望の出力装置から必要に応じて出力するようにしてもよい。
【００６４】
選択手段６は、生成手段４によって生成されたシナリオの各分岐のうち、上述した依存関係を有する分岐について上記セクションを選択するための手段であり、具体的には、図１に示すような入力装置１により実現される。すなわち、シナリオが上記表示装置５に表示され、設計者が上記分岐についてセクションを選択すると、選択手段６は、設計者の選択結果としてその選択されたセクションを入力する。
【００６５】
実行手段７は、選択手段６によって選択されたセクション間の実行順序に基づいて、第１のプログラムを模擬実行する。この模擬実行の結果は、上記表示手段５に表示されるようになっている。
【００６６】
拡張手段８は、上記依存関係に基づいて、上記シナリオと等価な挙動を導出し、それらの挙動が可能となるようにシナリオを拡張する。具体的には、上記シナリオについて、上記依存関係を有しないセクション同士の分岐を付加することによって拡張を行う。これら依存関係のない分岐の付加は、プログラムに、無害な非決定性をもたらす。
【００６７】
変換手段９は、拡張手段８によって拡張された上記シナリオに基づき第１のプログラムを変換して第２のプログラムを生成する。すなわち、拡張された上記シナリオに基づいて、選択された順序で一連の各セクションを実行する第２のプログラムに変換する。この変換では、上記シナリオ以外の挙動をしないように抑制する。具体的には、ソースコードに同期命令を埋め込むことにより、挙動の抑制を行う。
【００６８】
ここで、拡張手段８と変換手段９の具体的な構成例について示す。図３は、上記拡張手段８の具体的な構成及び拡張手段８と変換手段９との関係を概念的に示す機能ブロック図である。拡張手段８は、シナリオ分解手段１１と、シナリオ最適化手段１２とを有している。シナリオ分解手段１１は、上記シナリオを第１のプログラムに対応させて分解し、プロセス毎のシナリオを生成する。また、シナリオ分解手段１１は、単純にシナリオを分解するのではなく、分解した個々のシナリオの集合から最初のシナリオが再現できるように、シナリオ間の同期をとるための情報（同期命令）を付加する。
【００６９】
ここで、シナリオが有向グラフで表されている場合のシナリオ分解手段１１による分解について説明する。まず、図４及び図５に、シナリオ分解手段１１による同期命令を挿入する手順を示す。これらの図において、各プロセスにおける命令の実行を矢印のエッジで表し、命令前後の状態を円形のノードで表している。また、図４は、プロセス間に共有して使用される変数である共有変数がない場合を示し、図５は、プロセス間に共有変数がある場合を示す。
【００７０】
まず、図４（ａ）において、すべてのプロセスが共有変数をアクセスしない動作であるものとすると、同図（ｂ）に示すように、有向グラフの全ての分岐に同期命令を挿入する。すなわち、この図に示すシナリオでは、２つ目のノードで分岐しているため、その分岐の後に同期命令ｓ１，ｓ２を挿入する。次に、図５（ａ）において、共有変数をアクセスする命令ｒ，ｗをそれぞれ含むものとする。この場合、同図（ｂ）に示すように、上記各命令ｒ，ｗの前（または後）に同期命令ｓ０，ｓ３を、分岐の後に同期命令ｓ１，ｓ２を挿入する。
【００７１】
以上のようにして同期命令を挿入したものに対して、シナリオ分解手段１１は、各プロセス毎にプロセスがもとからもっていた命令と同期命令のみからなるグラフとして、プロセス毎のシナリオを生成する。
【００７２】
シナリオ最適化手段１２は、第１のプログラムを解析し、プロセス毎のシナリオに冗長な部分があればそれらを除去し、最適化されたシナリオ（最適化シナリオ）を生成する。すなわち、例えば上記同期命令の冗長なものを削除し、必要な同期命令のみを残す。この同期命令の削除は、グラフ縮約ルールを適用することによって行われる。図６及び図７に、このグラフ縮約ルールの一例を示す。図６は、プロセス間に共有変数がない場合を示し、図７は、プロセス間に共有変数がある場合を示す。なお、以下に示すルールを直接プログラムとして表すようにしてもよい。
【００７３】
まず、図６において、プロセス間に共有変数がない場合について示す。同図（ａ）に示すように、命令ａ１の後に分岐した同期命令ｓ１，ｓ２が挿入されており、その行き先が同じであり、同期命令ｓ１，ｓ２以外に同期命令がない場合、同期命令ｓ１，ｓ２は削除される（ｒｕｌｅ１）。また、同図（ｂ）に示すように、分岐がない状態で命令ａ１と命令ａ２の間に同期命令ｓ１が挿入されており、この同期命令ｓ１以外に同期命令がない場合、この同期命令は削除される（ｒｕｌｅ２）。更に、同図（ｃ）に示すように、命令ａ１の後に分岐したループ状の同期命令ｓ１が挿入されており、この同期命令ｓ１以外に同期命令がない場合、この同期命令ｓ１は削除される（ｒｕｌｅ３）。また、同期をとっている他のプロセス側の同期命令がすべて削除された場合は、対応する同期命令も削除される（ｒｕｌｅ４）。
【００７４】
次に、図７において、プロセス間に共有変数がある場合について示す。同図（ａ）に示すように、命令ａ１の後に分岐した同期命令ｓ１，ｓ２が挿入されており、その行き先が同じであり、同期命令ｓ１，ｓ２以外に同期命令がなく、かつ、命令ａ２が共有変数をアクセスする命令ではない場合、同期命令ｓ１，ｓ２は削除される（ｒｕｌｅ１）。また、同図（ｂ）に示すように、分岐がない状態で、命令ａ１と命令ａ２の間に同期命令ｓ１，ｓ２が挿入されており、これら同期命令ｓ１，ｓ２以外に同期命令がない場合、同期命令ｓ１のみが削除され同期命令ｓ２のみが残される（ｒｕｌｅ２）。更に、同図（ｃ）に示すように、命令ａ１の後に分岐したループ状の同期命令ｓ１が挿入されており、この同期命令ｓ１以外に同期命令がない場合、この同期命令ｓ１は削除される（ｒｕｌｅ３）。また、同期をとっている他のプロセス側の同期命令が削除された場合は、対応する同期命令も削除される（ｒｕｌｅ４）。
【００７５】
上記変換手段９は、最適化シナリオから、シナリオと、そのシナリオから拡張される挙動とのみを再現する第２のプログラムを生成する。具体的には、例えば上記のようにして残した同期命令を第２のプログラムを示すソースプログラムに付加することによって行う。
【００７６】
［２．作用及び効果］
上記のような構成を有する本実施の形態におけるプログラミングは、以下のような手順で行われる。ここで、図８は、本実施の形態におけるプログラミングの手順を示すフローチャートである。
【００７７】
［プログラムの作成処理］
まず、設計者は、エディタ１を用いて第１のプログラムを作成・入力する（ステップ８０１）。プログラムの作成は、例えば、対象の並行システムに対し、並行性を用いた自然なモデル化を行い、モデルを構成する各プロセスの構造と挙動とをコーディングすることによって行うことができる。この時点では、この第１のプログラムには、エラーが潜在的に存在する可能性がある。
【００７８】
次の表１は、本実施の形態において例として用いる並行プログラムを構成するプロセスＰ１，Ｐ２のソースコードの例である。
【００７９】
【表１】
0003641090.tif 000002
【００８０】
この例では、プロセスＰ１とＰ２間に何ら制御関係が存在しないので、各プロセスの各命令の実行順序は予測不能な悪い非決定性を帯びている。また、図９は、この時点でのプロセスＰ１，Ｐ２が各プロセッサＣ１，Ｃ２に対応する状態を示す概念図である。
【００８１】
［プロセスの区分処理］
このようにプログラムが作成されると、区分手段２が、第１のプログラムの前記各プロセスＰ１，Ｐ２を、実行制御可能なセクションに区分する（ステップ８０２）。すなわち、区分手段２は、第１のプログラムの各プロセスＰ１，Ｐ２に上述したシナリオポイントを設定することにより区分を行う。
【００８２】
このような区分は、各プロセスＰ１，Ｐ２に、割り込み可能なポイントを表すポイント（以下「シナリオポイント」という）を設定することによって行うことができる。シナリオポイントは、例えば各命令の前後に設定すればよく、また、プロセス内部のみでのローカルな一連の処理が存在するときは、その処理の途中ではなく処理の前後にシナリオポイントを設定してもよい。
【００８３】
すなわち、シナリオポイントで区切られた区間は割り込み禁止区間であるから、区間の途中で割り込むことはできず、したがって同期信号などによって実行制御を行うことができない。この結果、シナリオポイントで区切られた区間がセクションとなる。ここでは、各命令が１つのセクションを形成するようにシナリオポイントを指定するものとし、以下の説明では命令語そのものをセクション名として用いる。なお、プロセス中の同期命令は割り込みを明示的に発生させるので、自動的にシナリオポイントとなる。
【００８４】
［依存関係の検出処理］
次に、検出手段３が、プロセスの各セクション間の依存関係を検出する（ステップ８０３）。検出された依存関係は所定のメモリ領域に保存する。すなわち、検出手段３は、あるプロセスにある対象を変更する命令を検出すると、他の全てのプロセスにおいて、その対象が変更されることによって結果に影響を受ける全ての命令を検出する。そして、その変更する命令と、上記影響を受ける全ての命令との間に、依存関係が存在するとみなす。
【００８５】
例えば、共有メモリに対してあるデータを書き込む書き込み命令を検出した場合、他の全てのプロセスにおいて、そのデータを読み出す読み出し命令を検出する。そして、上記書き込み命令とその読み出し命令との間に依存関係が存在するとみなす。
【００８６】
ここでは、共有メモリに関連して
0003641090.tif 000003
の間に依存関係が検出されたものとする。
【００８７】
［シナリオの生成処理］
続いて、生成手段４が、上述したシナリオを生成する（ステップ８０４）。図１０はシナリオの一例であり、表１に例示したプログラムについて実行可能な全ての経路を状態遷移図で表現したシナリオの例である。シナリオを表すこのような状態遷移図をシナリオグラフと呼ぶ。この図では、各命令の実行を矢印のエッジで表し、命令前後の各状態を円形のノードで表している。なお、図１０に示すシナリオグラフは、遷移可能な経路を全て表した場合の図であり、そのような経路が１０通り存在することを示している。
【００８８】
また、本実施の形態におけるシナリオの生成では、各プロセスの各セクションの挙動順序を、依存関係を有するセクション同士の分岐に限定して表す。このようなシナリオの生成では、依存関係を有しないセクション同士の分岐については、いずれかのセクションを生成しない。例えば、図１０のノードｎ１２におけるｒｅａｄ１とｒｅａｄ２の分岐は、ｒｅａｄ１とｒｅａｄ２に依存関係が無いため、いずれが先でも結果は同じである。そのため、例えば、セクションｒｅａｄ２のエッジは生成せず、ｒｅａｄ１のエッジのみ生成する。
【００８９】
［分岐の選択処理］
次に、上記のように生成されたシナリオが、表示手段５によって表示される（ステップ８０５）。このとき、依存関係を有しないセクションについては、上記のようにいずれかの分岐のみが表示されるが、依存関係を有するセクション同士の分岐については、設計者が選択手段６を通じてセクションを選択する（ステップ８０６）。
【００９０】
例えば、図１０に示すノードｎ１１においては、ｉｎｉｔ１とｒｅａｄ２との間に依存関係がある。その場合、図１１に示すように、選択に係るノードｎ１１とセクションｉｎｉｔ１，ｒｅａｄ２のエッジが太線で強調表示されると共に、画面に選択のためのウインドウが表示される。
【００９１】
ウインドウにはメッセージと共に選択肢を表すアイコンが表示されており、設計者はマウスのポインタでいずれかのアイコンをポイントし、マウスのボタンをクリックすることによって所望のセクションを選択することができる。ここでは、ｉｎｉｔ１を先に実行するセクションとして選択し、ｒｅａｄ２を後に実行するセクションとして選択したものとする。すなわち、ｉｎｉｔ１よりｒｅａｄ２を先に実行すると初期化の前に読み込むことになり、バグとなるので選択しない。そして、選択されなかったエッジは削除される。図１２は、ノードｎ１１からのセクションｒｅａｄ２が削除された後のシナリオグラフの状態を示す図である。
【００９２】
また、エッジが削除される場合は、削除されたエッジのみを入力とするノードも遷移の可能性がなくなるため生成されない。すなわち、ノードｎ１１においてセクションｒｅａｄ２が選択された場合に生成されるはずであったノードｎ２１，ｎ３１，ｎ２２，ｎ３２は生成されない。ｎ１２においては、ｒｅａｄ１とｒｅａｄ２に依存関係がないので、そのような場合は、ノードｎ１２における分岐においてｒｅａｄ２は省略されｒｅａｄ１のエッジのみが生成される。
【００９３】
更に、セクション間に実質的に依存関係が存在しない場合や、セクションのいずれが先になる場合もそれぞれ意味のある動作を行う場合は、双方を選択してもよい。図１１のウインドウ中のアイコン「双方あり」は、このような選択を入力するためのものである。ここで、図１３は、ノードｎ１３についてｗｒｉｔｅ１とｒｅａｄ２から分岐を選択する場合の画面の表示例を示した図である。この状態で「双方あり」のアイコンを選択した場合は、エッジは削除されず、図１３に示すような状態のままとなる。
【００９４】
［模擬実行処理］
次に、上記のようにして選択を行った結果に基づき、設計者は、実行手段７を用いて第１のプログラムを模擬実行する（ステップ８０７）。すなわち、設計者は、セクションの選択を行うと、逐次第１のプログラムを模擬実行する。そして、その実行結果は、表示手段７に表示される（ステップ８０８）。その表示された実行結果により、設計者は第１のプログラム中にバグが存在するか否かを判断し（ステップ８０９）、バグが存在せず、結果が意図した通りであって、かつ、シナリオの生成処理が終了していない場合は（ステップ８１０）、設計者はシナリオの生成の処理を続行する（ステップ８０４）。一方、バグが存在し、結果が意図した通りでない場合は、設計者はエディタ１によって第１のプログラムのバグを修正する（ステップ８０１）。
【００９５】
例えば、図１４に示すように、分岐の選択処理（ステップ８０６）において、ノード１３のセクションｗｒｉｔｅ１，ｒｅａｄ２の双方が選択されている場合、この時点でシナリオグラフに残っているシナリオは、次の２通りの経路のシナリオｓｎ１，ｓｎ２を含む。
【００９６】
【表３】
0003641090.tif 000004
【００９７】
【表４】
0003641090.tif 000005
【００９８】
従って、実行手段７は、これら２通りのシナリオｓｎ１，ｓｎ２に従って模擬実行を行う。この結果、バグが存在せず、結果が意図した通りである場合、シナリオの生成処理（ステップ８０４）において、図１５に示すようなシナリオが生成される。ここでは、図１０に示すノードｎ２３において、セクションｗｒｉｔｅ１とｗｒｉｔｅ２に依存関係があり、ｎ１１の場合と同様に、セクションｗｒｉｔｅ１のエッジが選択された場合を示す。
【００９９】
このようにして、図１５の状態に到達したとき、シナリオグラフに表現されているシナリオは、次の２通りの経路のシナリオｓｎ１，ｓｎ２を含む。
【０１００】
【表５】
0003641090.tif 000006
【０１０１】
【表６】
0003641090.tif 000007
【０１０２】
この状態のシナリオは、並行プログラムについて無限に存在するテストケースの中で、設計者が期待する挙動を表現した本質的なものである。
【０１０３】
［シナリオの拡張処理］
次に、拡張手段８が、上記シナリオについて、依存関係を有しないセクション同士の分岐を付加することによって拡張する（ステップ８１１）。すなわち、拡張手段８は、検出手段３が検出した依存関係に基づき、依存関係を有していないために生成手段４によって生成されなかったエッジと、そのエッジの遷移先のノードをシナリオグラフ中に復元する。
【０１０４】
例えば、図１５に示すシナリオグラフを拡張した後の状態を図１６に示す。この図において、設計者の選択に基づいて残された挙動のエッジを細い実践の矢印で示し、拡張された挙動のエッジを太い実線の矢印で示し、シナリオグラフから削除された結果抑制される挙動のエッジを破線の矢印で示す。すなわち、ノードｎ１２から分岐しているセクションｒｅａｄ２と、ノードｎ２２と、そのノードｎ２２から分岐しているセクションｒｅａｄ１とが復元される。
【０１０５】
なお、生成手段４によって生成されなかったエッジ及びノードは、上記のように検出手段３が検出した依存関係に基づいて復元してもよいが、生成手段４がシナリオの原形の生成時にそれらのエッジ及びノードを記録しておき、この記録に基づいて復元するようにしてもよい。すなわち、図１７に示すように、生成手段４が所定のメモリ領域に上記エッジを記憶させておき、拡張手段８は、その情報のみを用いて拡張を行う。
【０１０６】
また、その場合、図１６において、削除されたエッジ及び削除されたエッジのみが経由するノードは参考に示したもので、実際にはこれらに関するデータはメモリ上から消去してかまわない。
【０１０７】
以上のように、依存関係のない分岐の付加により、プログラムに無害な非決定性がもたらされる。このため、変換後の第２のプログラムの非決定性が増大し、プログラムの並列性が向上する。
【０１０８】
［プログラムの変換処理］
次に、変換手段９が、このように得られたシナリオに基づいて、第１のプログラムを、前記選択に基づく順序で一連の前記各セクションを実行する第２のプログラムに変換する（ステップ８１２）。
【０１０９】
このような変換は、依存関係のあるセクション間で、全てのシナリオで実行が先とされたセクションの後に、プロセス間の同期信号の発信命令（送信セマフォア）を挿入し、全てのシナリオで実行が後とされたセクションの前に、上記同期信号の待ち受け命令（受信セマフォア）を挿入することによって行うことができる。これによって、セクション間の指定された先後関係が、プロセス間の同期信号によって容易かつ確実に実現される。
【０１１０】
図１６のシナリオに基づいて得られる第２のプログラムを次に示す。
【表７】
0003641090.tif 000008
【０１１１】
また、図１８は、表７に示した第２のプログラムの各プロセスが、同期命令によるタイミングに基づいて実行される状態を示す概念図である。この図において、プロセスＰ２のｒｅａｄ２は必ずプロセスＰ１のｉｎｉｔ１の後で実行されるが、これは、図１６のノードｎ１１においてｉｎｉｔ１が先、ｒｅａｄ２が後として選択されたことに対応する。
【０１１２】
また、図１８において、プロセスＰ２のｗｒｉｔｅ２は必ずプロセスＰ１のｗｒｉｔｅ１の後で実行されるが、これは、図１６のノードｎ２３においてｗｒｉｔｅ１が先、ｗｒｉｔｅ２が後として選択されたことに対応する。
【０１１３】
また、図１８において、プロセスＰ２のｒｅａｄ２について、プロセスＰ１の各セクションｒｅａｄ１，ｗｒｉｔｅ１のいずれとの間においても、先後関係が非決定的であるが、これは、図１６において、ｒｅａｄ１，ｗｒｉｔｅ１の前後の各ノードｎ１２，ｎ１３，ｎ１４のうち、いずれのノードからもｒｅａｄ２のエッジが存在することに対応する。これによって、並行プログラムのよい非決定性を含む無害な非決定性が維持される。
【０１１４】
ここで、拡張手段８及び変換手段９の具体的な処理について説明する。ここでは、図８におけるステップ８０１〜８１０において、図１９に示すような第１のプログラムが生成されたものとする。すなわち、図１９は、その第１のプログラムを構成するプロセスＰ１，Ｐ２のソースコードを示したものである。
【０１１５】
また、この第１のプログラムに基づいて、図２０に示すようなシナリオグラフが生成されたものとする。ここで、命令ｗ０，ｗ１，ｒは、共有変数をアクセスする命令であるものとする。更に、図２１は、拡張手段８及び変換手段９が第２のプログラムを生成する手順を示すフローチャートである。
【０１１６】
まず、シナリオ分解手段１１が、生成されたシナリオに同期命令を挿入する（ステップ２１０１）。すなわち、図２２に示すように、共有変数をアクセスする命令ｗ０，ｗ１，ｒの前とすべての分岐の後とに同期命令ｓ０〜ｓ３を挿入する。次に、シナリオ分解手段１１は、同期命令の挿入されたシナリオを、プロセスＰ１とＰ２とに分解する（ステップ２１０２）。このとき、すべての状態で２つのプロセスＰ１，Ｐ２が同期を取るという強い同期制約の基にシナリオの分解を行う。図２３に、分解したシナリオを示す。同図（ａ）はプロセスＰ１のシナリオを示し、同図（ｂ）はプロセスＰ２のシナリオを示す。これら２つのプロセスＰ１，Ｐ２は、同じ名前の同期命令ｓ０〜ｓ３が与えられることにより、同期をとるようになる。
【０１１７】
次に、シナリオ最適化手段１２が、上記シナリオを最適化する（ステップ２１０３）。すなわち、第１のプログラムを解析し、冗長な同期命令を削除する。具体的には、図２３に示す同期命令ｓ０〜ｓ３には冗長性があるため、必要な同期命令のみ残して冗長な同期命令を除去する。このとき、上述した図６及び図７に示すグラフ縮約ルールを適用する。すなわち、図２３（ｂ）に示すプロセスＰ２のシナリオにおいて、図７（ｃ）に示すｒｕｌｅ２と図７（ｃ）に示すｒｕｌｅ３とに基づいて同期命令ｓ２，ｓ３が削除される。また、図７（ｂ）に示すｒｕｌｅ２に基づいて、同期命令ｓ０が削除される。これに対応して、ｒｕｌｅ４に基づいて、プロセスＰ１のシナリオにおいて同期命令ｓ０，ｓ２，ｓ３が削除される。
【０１１８】
以上のようにして最適化されたシナリオグラフの例を、図２４に示す。同図において、（ａ）はプロセスＰ１の最適化されたシナリオグラフであり、（ｂ）はプロセスＰ２の最適化されたシナリオグラフである。この場合、同期命令ｓ１のみ残して他の同期命令はすべて削除されている。このような最適化は、すなわち、無害な非決定性の導入を行っていることに対応する。
【０１１９】
次に、変換手段９が、最終的な並行プログラムである第２のプログラムを生成する（ステップ２１０４）。このとき、上記シナリオの最適化において残された同期命令を、ソースコードに同期命令ｓｙｎｃ（＜ＩＤ＞）として埋め込む。すなわち、図２４に示す上記同期命令ｓ１を、同期命令ｓｙｎｃ（ｓ１）として挿入する。図２５は、第２のプログラムを示すソースコードである。
【０１２０】
このように、本実施の形態では、模擬実行によって妥当性を確認したシナリオおよびそれと等価な挙動しか示さないように、並行プログラムが抑制されるので、シナリオで与えた以外の非決定性は排除される。
【０１２１】
［効果］
以上説明したように、本形態ではプロセスが実行制御可能なセクションに区分され、各プロセスの各セクションのありうる挙動順序がシナリオで表される。このシナリオの各分岐について、先に実行すべきセクションのエッジを残し、他方のセクションの可能性を削除してゆくと、意図する実行順序の組み合わせのみがシナリオ上に残る。このようなシナリオに基づいて、第１のプログラムは、実行タイミング制御の命令の挿入によって第２のプログラムに変換され、第２のプログラムには悪い非決定性が存在しない。
【０１２２】
このように、本形態では、シナリオ上で実行順序を指定するだけで指定通りのプログラムが得られるので、信頼性の高い並行プログラムを容易に作成することができる。
【０１２３】
また、本実施の形態では、依存関係が存在しないために選択が不要な分岐については最初からシナリオに含まれないので、シナリオが単純化され理解容易となり、設計者が行う選択の回数も減少するので、プログラミングが効率化される。この場合、依存関係を有しないセクション同士の実行順序は悪い非決定性を生じないので、シナリオに含まれない場合でもプログラムの信頼性は低下しない。
【０１２４】
更に、本実施の形態では、シナリオを生成しつつシナリオ通りに第１のプログラムを模擬実行することができる。このため、実行結果によって選択内容の妥当性を確認したり、プログラム中のバグを発見することによって、プログラムの信頼性とプログラミングの効率が向上する。
【０１２５】
［３．他の実施の形態］
なお、本発明は上記実施の形態に限定されるものではなく、実施態様の変更は自由であるから、次に例示するような他の実施の形態をも包含するものである。例えば、プロセス（タスク）やＣＰＵの数は２つには限定されず、自由に定めることができる。
【０１２６】
また、上述した実施の形態では、依存関係を有しないセクションについては自動的に一方のみが選択されるようにし、依存関係を有するセクションについてのみ設計者が逐次選択するようにしたが、これに限らない。例えば、依存関係を有しないセクションについても、同様に設計者が選択するようにしてもよい。すなわち、ノード毎に設計者が選択を行うようにしてもよい。この場合、分岐の選択の後の拡張処理を不要とすることもできる。
【０１２７】
または、一旦仮に図１０に示すようなシナリオを生成してから、依存関係を有しないセクション同士の分岐について、いずれかのセクションを自動的に削除するようにしてもよい。例えば、上述したように、図１０に示すノードｎ１２におけるセクションｒｅａｄ１とｒｅａｄ２の分岐のように各セクションに依存関係がない場合、図２６に示すように、生成手段４は一方のセクション（例えばｒｅａｄ２）を削除する。
【０１２８】
また、依存関係を有する分岐については、例えば図２７に示すように、表示手段５が表示画面にシナリオグラフを表示し、設計者がセクションの選択を行う。この場合、選択は、依存関係に係る各セクションに対応するエッジが分岐しているノードを指摘し、いずれかのセクションに係るエッジを設計者が選択することによって行うことができる。図２７では、選択に係るノードｎ１１とエッジｉｎｉｔ１，ｒｅａｄ２が太線で強調表示されると共に、画面に選択のためのウインドウが現れている。図２８は、ノードｎ１１からのセクションｒｅａｄ２が削除された後のシナリオグラフの状態を示す図である。この後、削除されたセクションｒｅａｄ２のエッジのみを入力とするノードｎ２１，ｎ３１，ｎ２２，ｎ３２が順次削除される。図２９は、これらが順次削除された後のシナリオグラフの状態を示す図である。
【０１２９】
また、上述したように、設計者がウインドウ中のアイコン「双方あり」を選択した場合は、エッジは削除されない。図３０は、ノードｎ１３についてｗｒｉｔｅ１とｒｅａｄ２からの分岐を選択する場合の画面の表示例を示した図である。この状態で「双方あり」のアイコンを選択した場合は、エッジは削除されず、図３０の状態のままとなる。更に、設計者がノード２３についてｗｒｉｔｅ２を後として選択し、図３１のように削除すると、ノード３３もこれにともなって削除される。このようにして、図１５に示すようなシナリオグラフの状態となる。
【０１３０】
更に、このような場合、模擬実行は、設計者がその時点でシナリオグラフに残っている各経路について、エッジの登場順に、エッジに対応するプログラムのセクションの命令をインタプリタ形式で実行することによって実現できる。また、シナリオ上にいくつかの経路が存在するときは、マウスクリックによって模擬実行すべき経路上のエッジを選択するようにしてもよい。
【０１３１】
また、セクションの単位は命令単位には限定されず、ルーチンや関数など他の単位をセクションとしてもよい。また、シナリオにおいて一つのノードから発する分岐の数は２つには限定されず３つ以上でもよい。また、情報の表示や入力のための画面の表示形式も実施の形態に示したものには限定されず自由に定めることができる。
【０１３２】
図３２は、シナリオの表示や分岐の選択などを行うための画面の他の表示例を示す図である。同図に示す表示画面において、「タスク１」及び「タスク２」のウインドウでは、プログラム中に「ｓｎｐ（１）」等のシナリオポイントが設定されている。また、「グローバル状態グラフ」では、生成されたシナリオのシナリオグラフが表示されている。ここでは、ｓｎｐ４においてｓｎｐ５とｓｎｐ６との分岐の選択が必要となっており、「分岐選択」のウインドウが表示されている。更に、複数のプロセス間における共通のデータは「共有データ」として表示されている。
【０１３３】
更に、第２のプログラムにおいて、プロセス間の実行順序を定める手法は、同期信号の発信命令や待ち受け命令には限定されず、特定の処理を実行するためのトークンの授受など、他の手法によって実現してもよい。
【０１３４】
【発明の効果】
以上説明したように本発明によれば、高信頼な並行プログラムを容易に開発することができる。
【図面の簡単な説明】
【図１】本発明の実施の形態を実現するコンピュータの構成を示す機能ブロック図。
【図２】同実施の形態の構成を概念的に示す機能ブロック図。
【図３】同実施の形態における変換手段９の具体的な構成を示す機能ブロック図。
【図４】同実施の形態におけるシナリオ分解手段１１による同期命令の挿入を説明する図。
【図５】同実施の形態におけるシナリオ分解手段１１による同期命令の挿入を説明する図。
【図６】同実施の形態におけるグラフ縮約ルールを説明する図。
【図７】同実施の形態におけるグラフ縮約ルールを説明する図。
【図８】同実施の形態におけるプログラミングの手順を示すフローチャート。
【図９】同実施の形態において、当初のプロセスＰ１，Ｐ２が各プロセッサＣ１，Ｃ２に対応する状態を示す概念図。
【図１０】同実施の形態において、表１に例示したプログラムについてあり得る全ての経路を状態遷移図で表現したシナリオの例。
【図１１】同実施の形態において、ノードｎ１１についてｉｎｉｔ１とｒｅａｄ２から分岐を選択する場合の画面の表示例を示す図。
【図１２】同実施の形態において、ノードｎ１１についてｉｎｉｔ１を先として選択したシナリオグラフの状態を示す図。
【図１３】同実施の形態において、ノードｎ１３についてｗｒｉｔｅ１とｒｅａｄ２から分岐を選択する場合の画面の表示例を示す図。
【図１４】同実施の形態において、ノードｎ１３についてｗｒｉｔｅ１とｒｅａｄ２の双方を選択した場合のシナリオグラフの状態を示す図。
【図１５】同実施の形態において、設計者の期待する挙動を表現したシナリオを示す図。
【図１６】同実施の形態において、図１５のシナリオグラフを拡張した後の状態を示す図。
【図１７】同実施の形態において、生成手段４がエッジを記憶させておく例を示す図。
【図１８】同実施の形態において、表７に示した第２のプログラムの各プロセスが、同期命令によるタイミングに基づいて実行される状態を示す概念図。
【図１９】同実施の形態において、第１のプログラムの例を示すソースコード。
【図２０】同実施の形態において、図１９に示す第１のプログラムに基づいて生成されたシナリオグラフの例を示す図。
【図２１】同実施の形態における拡張手段８及び変換手段９の動作を説明するフローチャート。
【図２２】同実施の形態において、同期命令の挿入されたシナリオグラフの例。
【図２３】同実施の形態において、分解されたシナリオグラフの例。
【図２４】同実施の形態において、最適化されたシナリオグラフの例。
【図２５】同実施の形態における第２のプログラムの例を示すソースコード。
【図２６】同実施の形態において、ノードｎ１２からの依存関係がない分岐のうち、一方のｒｅａｄ２を削除した状態のシナリオグラフを示す図。
【図２７】同実施の形態において、表示画面にシナリオグラフを表示し、セクションの選択を行う場合の画面の表示例を示す図。
【図２８】同実施の形態において、ノードｎ１１からのセクションｒｅａｄ２が削除された後のシナリオグラフの状態を示す図。
【図２９】同実施の形態において、ノードｎ２１，ｎ３１，ｎ２２，ｎ３２が順次削除された後のシナリオグラフの状態を示す図。
【図３０】同実施の形態において、ノードｎ１３についてｗｒｉｔｅ１とｒｅａｄ２から分岐を選択する場合の画面の表示例を示した図。
【図３１】同実施の形態において、ノードｎ２３についてｗｒｉｔｅ２を後として選択し削除したシナリオグラフの状態を示す図。
【図３２】同実施の形態において、シナリオの表示や分岐の選択などを行うための画面の他の表示例を示す図。
【図３３】従来技術の問題点を説明するための図
【符号の説明】
Ｃ...プロセッサ
Ｐ...プロセス
Ｂ...バス及び入出力制御回路
Ｉ...入力装置
Ｏ...出力装置
Ｍ...共有メモリ
Ｓ...外部記憶装置
１...エディタ
２...区分手段
３...検出手段
４...生成手段
５...表示手段
６...選択手段
７...実行手段
８...拡張手段
９...変換手段
１１...シナリオ分解手段
１２...シナリオ最適化手段
【図１】
0003641090.tif 000009
【図２】
0003641090.tif 000010
【図３】
0003641090.tif 000011
【図４】
0003641090.tif 000012
【図５】
0003641090.tif 000013
【図６】
0003641090.tif 000014
【図７】
0003641090.tif 000015
【図８】
0003641090.tif 000016
【図９】
0003641090.tif 000017
【図１０】
0003641090.tif 000018
【図１１】
0003641090.tif 000019
【図１２】
0003641090.tif 000020
【図１３】
0003641090.tif 000021
【図１４】
0003641090.tif 000022
【図１５】
0003641090.tif 000023
【図１６】
0003641090.tif 000024
【図１７】
0003641090.tif 000025
【図１８】
0003641090.tif 000026
【図１９】
0003641090.tif 000027
【図２０】
0003641090.tif 000028
【図２１】
0003641090.tif 000029
【図２２】
0003641090.tif 000030
【図２３】
0003641090.tif 000031
【図２４】
0003641090.tif 000032
【図２５】
0003641090.tif 000033
【図２６】
0003641090.tif 000034
【図２７】
0003641090.tif 000035
【図２８】
0003641090.tif 000036
【図２９】
0003641090.tif 000037
【図３０】
0003641090.tif 000038
【図３１】
0003641090.tif 000039
【図３２】
0003641090.tif 000040
【図３３】
0003641090.tif 000041