(57)【特許請求の範囲】
【請求項１】
スレッド実行部が、プログラムを分割した複数のスレッドを並列して実行し、
スレッド制御部が、前記プログラムに前記複数のスレッド間において同期が成立した場合に実行される命令コードである第１の命令コードが存在する場合に、前記第１の命令コードの存在を示し、前記第１の命令コードの実行によりリセットされる第１のフラグを設定し、
前記スレッド制御部が、前記プログラムに前記第１の命令コードが存在する場合に、前記複数のスレッドの中で前記第１の命令コードが検出されたスレッドを表す第２のフラグを設定し、
前記スレッド実行部が、前記第２のフラグが設定された場合に、前記第２のフラグにより表されるスレッドにおいて、前記第１のフラグがリセットされるまで同期処理の実行を待つ
ことを特徴とするマルチスレッド処理方法。
【請求項２】
前記第１のフラグは、前記プログラムに存在する前記第１の命令コードであって実行されていないものの数を示す値を持ち、前記第１の命令コードが検出される毎に前記値がインクリメントされ、検出された前記第１の命令コードが実行される毎に前記値がデクリメントされる
ことを特徴とする請求項１に記載のマルチスレッド処理方法。
【請求項３】
前記第２のフラグは、前記第１のフラグがセットされた場合には更新を禁止され、前記第１のフラグがリセットされた場合に更新される
ことを特徴とする請求項１に記載のマルチスレッド処理方法。
【請求項４】
前記第１のフラグがリセットされた場合に、その時点でセットされている前記第２のフラグがリセットされる
ことを特徴とする請求項１に記載のマルチスレッド処理方法。
【請求項５】
前記スレッド実行部が、前記第２のフラグにより表されるスレッドにおいて、前記第１のフラグのリセットの後に、同期処理を実行する
ことを特徴とする請求項１に記載のマルチスレッド処理方法。
【請求項６】
前記プログラムは、前記第１の命令コードを含まないプログラム、又は、前記第１の命令コードを含むプログラムである
ことを特徴とする請求項１に記載のマルチスレッド処理方法。
【請求項７】
前記複数のスレッドの数がＮ個であり、前記Ｎ個のスレッドの各々が、バリアフラグの値のストア及びストアした前記バリアフラグの値の他のスレッドとの間でのロードを、ｌｏｇ２Ｎ回（小数点以下繰上げ）繰り返すことにより同期する
ことを特徴とする請求項１に記載のマルチスレッド処理方法。
【請求項８】
プログラムに複数のスレッド間において同期が成立した場合に実行される命令コードである第１の命令コードが存在する場合に、前記第１の命令コードの存在を示し、前記第１の命令コードの実行によりリセットされる第１のフラグと、前記プログラムを分割した複数のスレッドの中で前記第１の命令コードが検出されたスレッドを表す第２のフラグを設定するスレッド制御部と、
前記複数のスレッドを並列して実行するスレッド実行部であって、前記第２のフラグが設定された場合に、前記第２のフラグにより表されるスレッドにおいて、前記第１のフラグがリセットされるまで同期処理の実行を待つスレッド実行部とを備える
ことを特徴とするマルチスレッド処理装置。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、マルチスレッド処理方法及びマルチスレッド処理装置に関する。
【背景技術】
【０００２】
コンピュータシステムが、複数のＣＰＵ（Ｃｅｎｔｒａｌ  Ｐｒｏｃｅｓｓｉｎｇ  Ｕｎｉｔ）を備え、更に１個のＣＰＵが複数のＣＰＵコアを備える場合がある。このようなコンピュータシステムにおいては、複数のスレッド、換言すれば、マルチスレッドにおいて並列に処理を実行するマルチスレッド並列機能が採用される。
【０００３】
マルチスレッド並列機能においては、複数のスレッド、換言すれば、マルチスレッドの間で同期をとる必要がある。これにより、マルチスレッドの間で共有される共有データの一貫性を保証することができ、また、マルチスレッドの間における並列実行を調整することができる。
【０００４】
なお、スレッド処理装置において、第１のスレッドの実行前に実行されるべき第２のスレッドを少なくとも一つ指定し、第１のスレッドが実行されたのを受けて、指定された第２のスレッドのすべてが実行を終了しているか否かを判定し、第２のスレッドのすべてが実行を終了していると判定された場合に、第１のスレッドを実行することが提案されている。
【先行技術文献】
【特許文献】
【０００５】
【特許文献１】特開２００５−２５８９２０号公報
【発明の概要】
【発明が解決しようとする課題】
【０００６】
マルチスレッド並列機能における同期には、スレッドの数が増加しても、できるだけ高速な同期を取ることが要求される。また、マルチスレッド並列機能における同期には、種々の並列処理が実行される場合について、各々の並列処理に応じた同期を取ることが要求される。
【０００７】
本発明は、複数の並列化モデルについて高速な同期を取ることができるマルチスレッド処理方法を提供することを目的とする。
【課題を解決するための手段】
【０００８】
開示されるマルチスレッド処理方法は、スレッド実行部が、プログラムを分割した複数のスレッドを並列して実行し、スレッド制御部が、プログラムに複数のスレッド間において同期が成立した場合に実行される命令コードである第１の命令コードが存在する場合に、第１の命令コードの存在を示し、第１の命令コードの実行によりリセットされる第１のフラグを設定し、スレッド制御部が、プログラムに第１の命令コードが存在する場合に、複数のスレッドの中で第１の命令コードが検出されたスレッドを表す第２のフラグを設定し、スレッド実行部が、第２のフラグが設定された場合に、第２のフラグにより表されるスレッドにおいて、第１のフラグがリセットされるまで同期処理の実行を待つ。
【発明の効果】
【０００９】
開示されるマルチスレッド処理方法によれば、マルチスレッド並列機能において、複数の並列化モデルについて同一の同期ロジックで高速に同期することができる。
【図面の簡単な説明】
【００１０】
【図１】スレッド処理装置の構成の一例を示す図である。
【図２】スレッド処理装置の説明図である。
【図３】スレッド処理の一例を示す図である。
【図４】スレッド処理の一例を示す図である。
【図５】スレッド処理の一例を示す図である。
【図６】スレッド処理の一例を示す図である。
【図７】スレッド処理フローを示す。
【図８】スレッド処理フローを示す。
【図９】スレッド処理フローを示す。
【図１０】本発明者が検討したスレッド処理を示す。
【図１１】本発明者が検討したスレッド処理を示す。
【図１２】本発明者が検討したスレッド処理を示す。
【図１３】本発明者が検討したスレッド処理を示す。
【発明を実施するための形態】
【００１１】
マルチスレッドにおいて並列に処理を実行するマルチスレッド並列機能には、換言すれば、スレッド並列には、以下の2つの並列化モデルがある。第１の並列化モデル（以下、並列化モデル１という）は、処理の絶対量が確定している場合の並列化である。並列化モデル１が適用される処理としては、例えば、ループ、配列、代入等の処理がある。第２の並列化モデル（以下、並列化モデル２という）は、処理の絶対量が不確定な場合の並列化である。並列化モデル２が適用される処理としては、例えば、リスト検索、再帰的アルゴリズム等の処理がある。マルチスレッド並列機能のロジックとしては、ループを並列処理する並列化モデル１が主に使用されてきたが、リスト検索や再帰的アルゴリズムを並列処理する並列化モデル２が増加している。
【００１２】
並列化モデル１では、処理の絶対量、例えばループの繰り返し数を事前に知ることができる。このため、ループの実行を各スレッドに均等に分割することができる。これにより、並列化モデル１において、実行性能を向上させることができる。
【００１３】
並列化モデル２では、処理の絶対量、例えばリストの長さや再帰呼出の回数等を事前に知ることができない。このため、処理を均等に分割することができない。そこで、プログラムを相互に依存関係を持たない複数のブロックに分割し、分割したブロックを、空きスレッド、換言すれば、同期待ちのスレッドに割り当てる。これにより、並列化モデル２において、各スレッドに処理を均等に分割して、実行性能を向上させることができる。
【００１４】
図１０は、本発明者が検討したマルチスレッド並列機能の説明図であり、並列化モデル２における、複数のスレッド間の同期（以下、単に同期という）から未実行の命令コードへのジャンプを示す。
【００１５】
ここで、以下の並列化モデル２の説明においては、同期から未実行の命令コードへジャンプする処理の一例として、ＯｐｅｎＭＰのＴＡＳＫ構文を用いる。ＴＡＳＫ構文によれば、リスト検索や再帰的アルゴリズム等、処理の絶対量が決まっていない不規則なアルゴリズムを並列化することができる。
【００１６】
図１０に示すように、１つのプログラムが、ブロックＢ１０１〜Ｂ１０３、Ｂ２０１、Ｂ３０１に分割され、マルチスレッドにおいて、並列処理される。例えば、ブロックＢ１０１がスレッドａで実行される場合、ＴＡＳＫ構文で囲まれた領域の命令コードの実行を、他のスレッドにスケジューリングすることができる。例えば、ＴＡＳＫ構文指示行「！＄ＯＭＰ  ＴＡＳＫ」とＴＡＳＫ構文終了行「！＄ＯＭＰ  ＥＮＤ  ＴＡＳＫ」とにより囲まれたブロックＢ２０１及びＢ３０１が、ＴＡＳＫ構文で囲まれた領域である。図１０の場合、最初に出現するＴＡＳＫ構文を含むブロックＢ２０１に含まれる命令コードをスレッドｂにスケジューリングし、次に出現するＴＡＳＫ構文を含むブロックＢ３０１に含まれる命令コードをスレッドｃにスケジューリングすることができる。
【００１７】
スレッドｂ及びスレッドｃは、空きスレッド、換言すれば、ＢＡＲＲＩＥＲ構文等で同期待ちをしているスレッドである。従って、スレッドｂ及びスレッドｃは、同期から未実行の命令コード、換言すれば、ＴＡＳＫ構文で囲まれた領域に含まれる命令コードにジャンプすることになる。
【００１８】
ここで、マルチスレッド並列機能における同期について考察すると、適用される処理の相違から、並列化モデル１における同期には、高速であることが要求される。一方、並列化モデル２における同期には、前述したように、同期から未実行の命令コードへのジャンプが可能であることが要求される。従って、本来は、並列化モデル１及び並列化モデル２の双方をサポートした場合、並列化モデル１及び並列化モデル２について、別々の同期ロジックを用意することが望ましい。
【００１９】
図１１は、本発明者が検討したマルチスレッド並列機能の説明図であり、並列化モデル１及び並列化モデル２における同期について示す。
【００２０】
ＯｐｅｎＭＰのＢＡＲＲＩＥＲ構文、例えば「！＄ＯＭＰ  ＥＮＤ  ＳＩＮＧＬＥ」には、同期処理の実行が暗黙的に含まれている。従って、図１１に示すように、並列化モデル１（ＭＯＤＥＬ＃１）に、ＢＡＲＲＩＥＲ構文「！＄ＯＭＰ  ＥＮＤ  ＳＩＮＧＬＥ」が含まれる場合がある。また、並列化モデル２（ＭＯＤＥＬ＃２）に、同様に、ＢＡＲＲＩＥＲ構文「！＄ＯＭＰ  ＥＮＤ  ＳＩＮＧＬＥ」が含まれる場合がある。
【００２１】
このため、並列化モデル１及び並列化モデル２をサポートした場合、実際には、別々の同期ロジックを用意することはできず、並列化モデル１及び並列化モデル２の双方に対応した同期ロジックが必要となる。
【００２２】
一方、同期それ自体の実行時間（以下、同期コストという）は、並列して実行されるスレッドの数に比例する。このため、ＣＰＵコアの数の増加に伴って、並列して実行されるスレッドの数が増加すると、同期コストの増加が問題となる。換言すれば、バリア内の処理量の増加、同期のためのスレッド間の通信の増加が、各々のＣＰＵコアの処理の負担となり、性能低下を招く原因となる。
【００２３】
この結果、ＣＰＵコアの数を増加したとしても、コンピュータの性能がＣＰＵコアの数を増加に比例して向上しなくなる。また、マルチスレッド並列機能による処理時の性能が、逐次処理時の性能よりも劣化する可能性が生じてしまう。
【００２４】
そこで、本発明者は、並列化モデル１及び並列化モデル２に別々の同期ロジックを適用する代わりに、並列化モデル１及び並列化モデル２の双方に適用することができる高速な同期ロジックについて検討した。
【００２５】
図１２及び図１３は、本発明者が検討したスレッド並列処理を示す。特に、図１２は、並列化モデル１において用いられる同期ロジックであるカスケード方式を示す。また、図１３は、カスケード方式を並列化モデル２の同期ロジックとして適用する場合における問題点を示す。
【００２６】
図１２に示すように、並列化モデル１における同期ロジックとして、カスケード方式が適用される。カスケード方式の同期は、マスターとなるスレッドが存在せず、各スレッドがｌｏｇ２Ｎ回（小数点以下繰上げ）のバリアフラグのロード及び／又はストアを繰り返すことにより実現される同期である。Ｎはスレッドの数である。
【００２７】
図１２において、同期には、「ｌｏｇ２Ｎ個のバリアフラグ×スレッド数」の領域を使用する。この場合、スレッドの数Ｎは「５」であるので、３個のバリアフラグを１組として５組使用する。５個のスレッド＃０〜＃４に対応するバリアフラグの設定領域を、各々、同期領域＃０〜＃４とする。同期領域＃０〜＃４は、各々、３個のバリアフラグを設定することができるようにされる。
【００２８】
ｓｔｅｐ＃１において、スレッド＃Ｎは、同期領域Ｎのi番目のバリアフラグを設定する。ここで、変数ｉは「１」から開始される。例えば、スレッド＃０は、同期領域＃０の１番目のバリアフラグを設定する（換言すれば、ストアする）。図１２においては、同期領域＃０の１番目のバリアフラグの設定が、同期領域＃０の１番目の領域に網掛けにより示される。他のスレッド＃１〜＃４においても、同期領域＃１〜＃４の１番目のバリアフラグが設定される。
【００２９】
ｓｔｅｐ＃２において、スレッド＃Ｎは、同期領域「（Ｎ＋Σ２ｊ）％スレッド数」のｉ番目のバリアフラグをロードする。ここで、変数ｊは「０」から開始される。この場合、同期領域「（Ｎ＋１）％５」の1番目のバリアフラグがロードされる。例えば、スレッド＃０についての同期領域＃０の１番目のバリアフラグは、スレッド＃１についての同期領域＃１の１番目の領域にロードされる。
【００３０】
スレッド＃Ｎは、ｓｔｅｐ＃２においてロードしたバリアフラグが設定済みの場合、変数ｉをインクリメントしてｓｔｅｐ＃３に進む。
【００３１】
ｓｔｅｐ＃３において、スレッド＃Ｎは、同期領域Ｎのi番目のバリアフラグを設定する。例えば、スレッド＃０は、同期領域＃０の２番目のバリアフラグを設定する。他のスレッド＃１〜＃４においても、同期領域＃１〜＃４の２番目のバリアフラグが設定される。
【００３２】
ｓｔｅｐ＃４において、スレッド＃Ｎは、同期領域「（Ｎ＋Σ２ｊ）％スレッド数」のｉ番目のバリアフラグをロードする。この場合、同期領域「（Ｎ＋２）％５」の２番目のバリアフラグがロードされる。例えば、スレッド＃０についての同期領域＃０の２番目のバリアフラグは、スレッド＃２についての同期領域＃２の２番目の領域にロードされる。
【００３３】
スレッド＃Ｎは、ｓｔｅｐ＃４においてロードしたバリアフラグが設定済みの場合、変数ｉをインクリメントしてｓｔｅｐ＃５に進む。
【００３４】
ｓｔｅｐ＃５において、スレッド＃Ｎは、同期領域Ｎの３番目のバリアフラグを設定する。例えば、スレッド＃０は、同期領域＃０の３番目のバリアフラグを設定する。他のスレッド＃１〜＃４においても、同期領域＃１〜＃４の３番目のバリアフラグが設定される。
【００３５】
ｓｔｅｐ＃６において、スレッド＃Ｎは、同期領域「（Ｎ＋Σ２ｊ）％スレッド数」のｉ番目のバリアフラグをロードする。この場合、同期領域「（Ｎ＋４）％５」の３番目のバリアフラグがロードされる。例えば、スレッド＃０についての同期領域＃０の３番目のバリアフラグは、スレッド＃４についての同期領域＃４の３番目の領域にロードされる。
【００３６】
スレッド＃Ｎにおいて、ｓｔｅｐ＃６においてロードしたバリアフラグが設定済みの場合、バリア同期が成立する。
【００３７】
本発明者の検討によれば、このような並列化モデル１における同期ロジックであるカスケード方式を並列化モデル２に適用すると、同期が成立していないにも拘わらず、スレッドが同期を終えてしまう。これは、並列化モデル２の同期において、同期から未実行の命令コードへのジャンプが可能であることに起因している。
【００３８】
図１３に示すように、ｓｔｅｐ＃１において、スレッド＃Ｎは、同期領域Ｎのi番目のバリアフラグを設定する。従って、前述したように、スレッド＃０〜４は、各々、同期領域＃０〜４の１番目のバリアフラグを設定する。この後、ｓｔｅｐ＃２において、スレッド＃Ｎは、同期領域「（Ｎ＋Σ２ｊ）％スレッド数」のｉ番目のバリアフラグをロードするはずである。
【００３９】
ところが、この場合、スレッド＃４が未実行の命令コードにジャンプしたことで、同期が未成立の状態となっているが、スレッド＃１は同期を終了してしまっている。具体的には、スレッド＃４が、ＴＡＳＫ構文で囲まれた領域に、同期からのジャンプにより実行される命令コード「ｃａｌｌ  ｔｒａｖｅｒｓｅ（Ｐ）」を含む。このため、スレッド＃４は、この命令コードを実行することにより、ｓｔｅｐ＃１の実行後かつｓｔｅｐ＃２の実行前に、一点鎖線で示すように、同期から実行にジャンプする。換言すれば、スレッド＃４は、命令コード「ｃａｌｌ  ｔｒａｖｅｒｓｅ（Ｐ）」により、未実行の命令コードへジャンプする。しかし、この場合、スレッド＃４が実行にジャンプしたにも拘わらず、スレッド＃１は、同期を終了してしまっている。このため、同期において必要とされる、同期後の命令コードが同期前の全ての実行が終了するまで実行されないことが、保証されないことになる。
【００４０】
具体的には、スレッド＃１の１番目のバリアフラグがスレッド＃２にロードされるので、スレッド＃２の２番目のバリアフラグがストアされる。このスレッド＃２の２番目のバリアフラグがスレッド＃４にロードされるので、スレッド＃４の３番目のバリアフラグがストアされる。このスレッド＃４の３番目のバリアフラグがスレッド＃３にロードされるので、スレッド＃３ではバリア同期が成立する。この結果、スレッド＃３は、同期から抜けて、同期後の命令コードを、同期前の全ての実行が終了する前に実行してしまう。
【００４１】
開示されるマルチスレッド処理装置及び方法は、マルチスレッド並列機能、換言すれば、スレッド並列において、複数の並列化モデルについて同一の同期ロジックで高速に同期することができる。
【００４２】
図１は、スレッド処理装置の構成の一例を示す図である。
【００４３】
図１に示すように、スレッド処理装置は、複数のＣＰＵ１と、メインメモリ２とを含む。ＣＰＵ１の数は２個に限られない。複数のＣＰＵ１とメインメモリ２との間は、バス３により相互に接続される。メインメモリ２は、複数のＣＰＵ１により使用される。
【００４４】
ＣＰＵ１は、複数のＣＰＵコア１２、複数のキャッシュ１３、共用キャッシュ１４を含む。ＣＰＵ１におけるＣＰＵコア１２の数は２個に限られない。キャッシュ１３はＣＰＵコア１２に対応して設けられる。共用キャッシュ１４は、ＣＰＵ１において１個設けられ、複数のＣＰＵコア１２により共用される。
【００４５】
複数のＣＰＵコア１２上で、複数のスレッド１１が並列に実行される。換言すれば、複数のＣＰＵコア１２は、プログラムを分割した複数のスレッド１１を並列して実行する。従って、複数のＣＰＵコア１２がスレッド実行部であると考えてよい。複数のスレッド１１の並列実行は、スレッド実行部である複数のＣＰＵコア１２がライブラリ２１を参照することにより、ライブラリ２１に従って制御される。従って、複数のＣＰＵコア１２及びライブラリ２１がスレッド制御部であると考えてよい。
【００４６】
なお、図１の例においては、１個のＣＰＵコア１２上で、１個のスレッド１１が実行される。ここで、ＣＰＵコア１２は、物理ＣＰＵコアであるが、これに限られず、論理的なＣＰＵコアであっても良い。
【００４７】
メインメモリ２は、ライブラリ（スレッドライブラリ）２１と、実行可能ファイル２２とを含む。ライブラリ２１は、メインメモリ２に予め用意される。実行可能ファイル２２は、図２を参照して後述するように、例えば、ソースプログラムをコンパイルすることにより得られる。実行可能ファイル２２は、実行可能な形式とされた１個のプログラムである。ライブラリ２１は、実行可能ファイル２２に対応して、換言すれば、プログラム（従って、ソースプログラム）毎に設けられる。
【００４８】
ライブラリ２１は、ｔａｓｋフラグ領域２１１と、ｉｄフラグ領域２１２と、バリアフラグ領域２１３とを含む。ｔａｓｋフラグ領域２１１は、スレッド１１がｔａｓｋフラグを設定する領域である。ｉｄフラグ領域２１２は、スレッド１１がｉｄフラグを設定する領域である。バリアフラグ領域２１３は、スレッド１１がバリアフラグを設定する領域である。
【００４９】
ｔａｓｋフラグ領域２１１は、１個だけ、換言すれば、プログラム毎に設けられる。ｉｄフラグ領域２１２は、１個だけ、換言すれば、プログラム毎に設けられる。従って、ｉｄフラグ及びｔａｓｋフラグは、プログラム全体で1個、換言すれば、ｓｈａｒｅｄ変数である。
【００５０】
前述したように、同期には「ｌｏｇ２Ｎ個のバリアフラグ×スレッド数」の領域を使用するので、バリアフラグ領域２１３は各々のスレッド１１に対応して設けられ、かつ、各々のバリアフラグ領域２１３はｌｏｇ２Ｎ個のフラグを設定できるようにされる。Ｎはスレッド１１の数である。
【００５１】
図２は、スレッド処理装置の構成の説明図である。
【００５２】
実行可能ファイル２２は、ソースプログラム４１をコンパイラ４２によりコンパイルすることにより得られる。例えば、ソースプログラム４１及びコンパイラ４２は、スレッド処理装置以外のコンピュータに設けられ、コンパイルにより得られた実行可能ファイル２２がメインメモリ２に格納される。
【００５３】
ソースプログラム４１は、例えば、同期からのジャンプにより実行される命令コードを含まないことにより、処理の絶対量が確定しているプログラムである。この場合、ソースプログラム４１は、例えば、ループ、配列、代入等の処理を含むプログラムである。処理の絶対量は、例えばループの繰り返し数であり、事前に知ることができる。
【００５４】
ここで、同期からのジャンプにより実行される命令コードを、第１の命令コードということとする。第１の命令コード以外の命令コード、換言すれば、同期からのジャンプによっては実行されない命令コードを、第２の命令コードということとする。
【００５５】
ソースプログラム４１が第１の命令コードを含まない場合には、ソースプログラム４１は、並列化モデル１の並列化指示行を含む。並列化モデル１の並列化指示行は、並列化モデル１によりスレッドを並列実行することを指示する。
【００５６】
また、ソースプログラム４１は、例えば、第１の命令コードを含むことにより処理の絶対量が不確定なプログラムである。この場合、ソースプログラム４１は、例えば、リスト検索、再帰的アルゴリズム等の処理を含むプログラムである。処理の絶対量は、例えばリストの長さや再帰呼出の回数等であり、事前に知ることができない。
【００５７】
ソースプログラム４１が第１の命令コードを含む場合には、ソースプログラム４１は、並列化モデル２の並列化指示行を含む。並列化モデル２の並列化指示行は、例えばＯｐｅｎＭＰのＴＡＳＫ構文指示行である。並列化モデル２の並列化指示行は、並列化モデル２によりスレッドを並列実行することを指示する。
【００５８】
コンパイラ４２は、並列化指示行を解析して、ライブラリ２１を呼び出すライブラリ呼出指示を生成する。なお、コンパイラ４２が、ソースプログラム４１が並列化可能であるか否かを解析して、並列化ライブラリを追加するようにしても良い。
【００５９】
以上により、実行可能ファイル２２が生成される。実行可能ファイル２２は、ソースプログラム４１をコンパイルした結果として、例えば、ＯｐｅｎＭＰのＴＡＳＫ構文指示行を含む。実行可能ファイル２２は、ＴＡＳＫ構文で囲まれた命令コードを実行することにより、当該ＴＡＳＫの実行へジャンプする。実行可能ファイル２２は、ソースプログラム４１をコンパイルした結果として、同期指示行を含む。実行可能ファイル２２は、同期指示行を実行することにより、同期処理を実行する。
【００６０】
前述したように、ＴＡＳＫ構文は、リスト検索、再帰的アルゴリズム等のような、処理の絶対量が決まっていない不規則なアルゴリズムを並列化する構文である。従って、実行可能ファイル２２はリスト検索、再帰的アルゴリズム等の処理を実行するプログラムであり、実行可能ファイル２２には前述の並列化モデル２が適用される。
【００６１】
なお、処理の絶対量が決まっていない不規則なアルゴリズムを並列化することにより実行されるプログラムは、ＴＡＳＫ構文を含むプログラムに限られない。換言すれば、ＴＡＳＫ構文に代えて、処理の絶対量が決まっていない不規則なアルゴリズムを並列化する構文を含むプログラムであれば、並列化モデル２により並列化される。従って、開示される例は、ＴＡＳＫ構文以外の処理の絶対量が決まっていない不規則なアルゴリズムを並列化する構文を含むプログラムについての同期処理に適用することができる。
【００６２】
実行可能ファイル２２は、相互に依存関係を持たない複数のブロック即ちスレッド１１に分割されて、並列実行される。従って、ＴＡＳＫ構文指示行を含むスレッド１１と、ＴＡＳＫ構文指示行を含まないスレッド１１とが存在する。また、複数のスレッド１１は、各々、同期指示行を含む。同期指示行は、ライブラリ２１による同期処理の実行を指示する。
【００６３】
一方、ライブラリ２１は、図１に示すｔａｓｋフラグ領域２１１、ｉｄフラグ領域２１２及びバリアフラグ領域２１３に加えて、ＴＡＳＫ構文検出部２１４、ＴＡＳＫ構文終了部２１５、同期処理部２１６を含む。
【００６４】
ＴＡＳＫ構文検出部２１４は、当該スレッド１１、換言すれば、プログラムに第１の命令コードが存在する場合に、ｔａｓｋフラグ領域２１１にｔａｓｋフラグ（第１のフラグ）を設定する。ｔａｓｋフラグは、プログラム、換言すれば、実行可能ファイル２２における第１の命令コードの存在を示す。具体的には、ｔａｓｋフラグは、第１の命令コードが検出される毎に「＋１」だけインクリメントされる。ｔａｓｋフラグの初期値は、例えば「０」とされる。従って、ｔａｓｋフラグの値は、基本的には、プログラムに存在する第１の命令コードの数を示す。
【００６５】
一方、ＴＡＳＫ構文検出部２１４は、当該スレッド１１に第１の命令コードが存在しない場合には、換言すれば、当該スレッド１１に第２の命令コードのみが存在する場合には、ｔａｓｋフラグ領域２１１にｔａｓｋフラグを設定しない。
【００６６】
また、ＴＡＳＫ構文検出部２１４は、当該スレッド１１、換言すれば、プログラムに第１の命令コードが存在する場合に、ｉｄフラグ領域２１２にｉｄフラグ（第２のフラグ）を設定する。ｉｄフラグは、複数のスレッド１１の中で第１の命令コードが検出されたスレッド１１を表す。ｉｄフラグとしては、ＴＡＳＫ構文検出部２１４を実行中のスレッド１１のスレッド番号が用いられる。スレッド番号は、予め定められ、スレッド１１を一意に定める識別情報である。ｉｄフラグ領域の初期値は、例えば「−１」、換言すれば、スレッド番号が取りえない値とされる。
【００６７】
更に、ＴＡＳＫ構文検出部２１４は、ｔａｓｋフラグが設定された場合には、その後に第１の命令コードを検出しても、当該検出をしたスレッド１１を示す新たなｉｄフラグを設定しない。換言すれば、ｔａｓｋフラグが設定された場合には、ｉｄフラグの更新は、禁止される。従って、ｉｄフラグは、ｔａｓｋフラグがリセットされた場合に、更新される。
【００６８】
これに加えて、ＴＡＳＫ構文検出部２１４は、ｉｄフラグが設定された場合、換言すれば、ｉｄフラグが「−１」以外の値である場合には、その後に第１の命令コードを検出しても、当該検出をしたスレッド１１を示す新たなｉｄフラグを設定しない。換言すれば、ｉｄフラグが設定された場合には、ｉｄフラグの更新は、禁止される。従って、ｉｄフラグは、その値が「−１」である場合に、更新される。これにより、ｉｄフラグにより示される１個のスレッド１１が必ず同期の成立を待つことになる。この結果、同期後の命令コードが同期前の全ての実行が終了するまで実行されないことを、保証することができる。
【００６９】
一方、ＴＡＳＫ構文検出部２１４は、当該スレッド１１に第１の命令コードが存在しない場合には、換言すれば、当該スレッド１１に第２の命令コードのみが存在する場合には、ｉｄフラグ領域２１２にｉｄフラグを設定しない。
【００７０】
ＴＡＳＫ構文終了部２１５は、当該スレッド１１、換言すれば、プログラムに存在する第１の命令コードが実行された場合に、ｔａｓｋフラグをデクリメントする。具体的には、ｔａｓｋフラグは、第１の命令コードが実行される毎に「−１」だけデクリメントされる。従って、ｔａｓｋフラグの値は、実際には、プログラムに存在する第１の命令コードであって実行されていない第１の命令コードの数を示す。一旦インクリメントされたｔａｓｋフラグがデクリメントされて「０」となった状態をリセットという。
【００７１】
同期処理部２１６は、カスケード方式による同期処理を実行する。これにより、複数のスレッド１１は、各々、カスケード方式により同期する。カスケード方式による同期においては、マスターとなるスレッドが存在しない。マスターとなるスレッドが存在しないので、全てのスレッドが均等な処理を実行することができる。
【００７２】
また、同期処理部２１６は、ｔａｓｋフラグがリセットされた場合に、その時点で設定されているｉｄフラグをリセットする。これにより、前述したように、新たなｉｄフラグを設定することができる。一旦「−１」以外の値とされたｉｄフラグが再度「−１」とされた状態をリセットという。
【００７３】
図２において、例えば、第１のスレッド１１（図３におけるスレッド＃０）は、実行可能ファイル２２の先頭行から順に処理を実行して、ＴＡＳＫ構文指示行に到達する。これに応じて、第１のスレッド１１は、ライブラリ２１のＴＡＳＫ構文検出部２１４を参照、換言すれば、実行する。これにより、第１のスレッド１１は、詳しくは図３〜図６を参照して後述するように、ｉｄフラグとｔａｓｋフラグを設定する。換言すれば、スレッド制御部により、ｔａｓｋフラグとｉｄフラグとが設定される。これにより、同期処理部２１６は、並列化モデル１によるスレッド並列処理及び並列化モデル２によるスレッド並列処理の双方について、カスケード方式による同期処理を実行することができる。
【００７４】
第１のスレッド１１は、ＴＡＳＫ構文指示行を実行した後、当該ＴＡＳＫ構文で囲まれた命令コードを第２のスレッド１１にスケジューリングし、更に、その後、当該ＴＡＳＫ構文終了行を検出する。なお、ＴＡＳＫ構文指示行とＴＡＳＫ構文終了行とを合わせて、ＴＡＳＫ構文という。ＴＡＳＫ構文終了行を検出した第１のスレッド１１は、当該ＴＡＳＫ構文終了行の次の行から順に処理を実行して、同期指示行に到達する。これに応じて、第１のスレッド１１は、ライブラリ２１の同期処理部２１６を参照して実行する。
【００７５】
この時、ｉｄフラグには、ＴＡＳＫ構文指示行、換言すれば、第１の命令コードを検出した第１のスレッド１１を示すスレッド番号が設定されている。従って、第１のスレッド１１は、同期処理を実行しない。
【００７６】
一方、第２のスレッド１１（図３におけるスレッド＃１、＃２）は、ＴＡＳＫ構文で囲まれた命令コードの実行にジャンプする。この後、第２のスレッド１１は、ＴＡＳＫ構文で囲まれた命令コードの実行を終了すると、これに応じて、ライブラリ２１のＴＡＳＫ構文終了部２１５を参照して実行する。これにより、第２のスレッド１１は、詳しくは後述するように、ｔａｓｋフラグをデクリメントする。この後、第２のスレッド１１は、同期指示行に到達して、これに応じて、ライブラリ２１の同期処理部２１６を参照して実行する。
【００７７】
この時、ｔａｓｋフラグのデクリメントに応じて、同期処理を実行せずに同期待ちの状態にあった第１のスレッド１１が、同期処理部２１６により、ｉｄフラグをデクリメントする。これにより、第１のスレッド１１は、同期処理を実行することができる。
【００７８】
ここで、複数のスレッド１１は、各々、ｌｏｇ２Ｎ回（小数点以下繰上げ）のバリアフラグのロード及びストアを繰り返すことにより同期する。Ｎはスレッド１１の数である。ｌｏｇ２Ｎ回というロードの回数は最低必要回数である。バリアフラグの初期値は、例えば「０」とされる。ロードしたバリアフラグが未設定である（「０」である）場合には、設定済みの（「１」である）バリアフラグがロードされるまで、ロードが繰り返される。
【００７９】
このカスケード方式の同期において、同期処理部２１６は、ｉｄフラグが設定された場合に、ｉｄフラグにより表されるスレッド１１において、同期処理を実行することなく、ｔａｓｋフラグがリセットされるまで同期処理の実行を待つ。換言すれば、同期処理部２１６は、ｉｄフラグが設定された場合に、ｉｄフラグにより表されるスレッド１１において、バリアフラグを設定しない（換言すれば、バリアフラグの「１」をストアしない）。
【００８０】
従って、同期処理部２１６は、ｉｄフラグにより示されるスレッド１１において、ｔａｓｋフラグのリセットの後に、同期処理を実行する。換言すれば、同期処理部２１６は、ｉｄフラグが設定された場合に、ｉｄフラグにより表されるスレッド１１において、バリアフラグを設定する（換言すれば、ストアする）。これにより、ｉｄフラグにより示されるスレッド１１においては、ｔａｓｋフラグがリセットされるまで、同期処理が実行されないことを保証することができる。この結果、同期後の命令コードが同期前の全ての実行が終了するまで実行されないこと、換言すれば、同期前の全ての実行が終了するまで同期が成立しないことを保証することができる。
【００８１】
以上のように、スレッド１１は、ＴＡＳＫ構文終了行を実行した後、同期指示行を検出する。これに応じて、スレッド１１は、ライブラリ２１の同期処理部２１６を参照、換言すれば、実行する。これにより、スレッド１１は、詳しくは後述するように、ｉｄフラグにより示されるスレッド１１においては、ｔａｓｋフラグのリセットを待って、同期処理を実行する。換言すれば、スレッド実行部は、ｉｄフラグが設定された場合に、ｉｄフラグにより表されるスレッドにおいて、同期処理を実行することなく、ｔａｓｋフラグがリセットされるまで同期処理の実行を待つ。
【００８２】
図３は、スレッド処理の一例を示す図である。なお、図３において、スレッド＃１及び＃２は、スレッド＃０が処理を終了した後、換言すれば、「ＥＮＤ  ＳＵＢＲＯＵＴＩＮＥ」を実行した後に、ｔａｓｋフラグをデクリメントするものとする。また、スレッド＃１がｔａｓｋフラグをデクリメントする前に、スレッド＃２のジャンプと共にｔａｓｋフラグがインクリメントされるものとする。
【００８３】
図３に示すプログラム即ち実行可能ファイル２２が複数のブロック即ちスレッド１１に分割されて、複数のスレッド１１、換言すれば、スレッド＃０〜＃２が並列に実行される。なお、図３において、例えば、「！＄ＯＭＰ  ＴＡＳＫ」がＴＡＳＫ構文指示行であり、「！＄ＯＭＰ  ＥＮＤ  ＴＡＳＫ」がＴＡＳＫ構文終了行であり、ＴＡＳＫ構文で囲まれた「ｃａｌｌ  ｔｒａｖｅｒｓｅ（Ｐ％ｌｅｆｔ）」等が第１の命令コードであり、「ＩＦ（ａｓｓｏｃｉａｔｅｄ（Ｐ％ｌｅｆｔ）」等が第２の命令コードである。
【００８４】
例えば、スレッド＃０が、スレッド＃１及び＃２と同様に、同期（ＥＮＤ  ＳＩＮＧＬＥ）で待機中であるとする。この同期（ＥＮＤ  ＳＩＮＧＬＥ）で待機中のスレッド＃０が、実行可能ファイル２２の先頭のブロックを実行する。換言すれば、スレッド＃０は、同期から、プログラムの先頭の「ｓｕｂｒｏｕｔｉｎ  ｔｒａｖｅｒｓｅ（Ｐ）」の実行にジャンプする。これにより、スレッド＃０は、サブルーチンＰの先頭行から順に命令コードを実行して、最初のＴＡＳＫ構文指示行に到達する。
【００８５】
ＴＡＳＫ構文指示行は、第１の命令コードではないが、第１の命令コードを含むことを示す命令コードである。従って、第１の命令コードではなく、ＴＡＳＫ構文指示行の存在に応じて、ｔａｓｋフラグ及びｉｄフラグが設定される。スレッド＃０は、ライブラリ２１のＴＡＳＫ構文検出部２１４を実行することにより、ｔａｓｋフラグ及びｉｄフラグを設定する。具体的には、ｔａｓｋフラグは、初期値「０」を「＋１」だけインクリメントすることにより、「１」とされる。ｉｄフラグは、初期値「−１」に代えて、当該スレッド＃０のスレッド番号「０」とされる。
【００８６】
この後、スレッド＃０は、最初のＴＡＳＫ構文指示行の次の行の第１の命令コード「ｃａｌｌ  ｔｒａｖｅｒｓｅ（Ｐ％ｌｅｆｔ）」を、例えば同期（ＥＮＤ  ＳＩＮＧＬＥ）で待機中のスレッド＃１にスケジューリングし、ＴＡＳＫ構文終了行を検出すると、当該ＴＡＳＫ構文終了行の次の行を実行する。
【００８７】
この後、スレッド＃０は、次のＴＡＳＫ構文指示行に到達する。これに応じて、スレッド＃０は、ＴＡＳＫ構文検出部２１４を実行することにより、ｔａｓｋフラグを「＋１」だけインクリメントする。この時点では、ｉｄフラグの値が「−１」以外の値であるので、ｉｄフラグは更新されない。
【００８８】
この後、スレッド＃０は、次のＴＡＳＫ構文指示行の次の第１の命令コード「ｃａｌｌ  ｔｒａｖｅｒｓｅ（Ｐ％ｒｉｇｈｔ）」を、例えば同期（ＥＮＤ  ＳＩＮＧＬＥ）で待機中のスレッド＃２にスケジューリングし、ＴＡＳＫ構文終了行を検出すると、当該ＴＡＳＫ構文終了行の次の行を実行する。
【００８９】
この後、スレッド＃０は、最後の指示行、換言すれば、処理の終了を指示する「ＥＮＤ  ＳＵＢＲＯＵＴＩＮＥ」に到達し、同期処理部２１６による同期処理を実行して、同期待ち（ＥＮＤ  ＳＩＮＧＬＥで待機中）となる。
【００９０】
一方、同期（ＥＮＤ  ＳＩＮＧＬＥ）で待機中のスレッド＃１は、最初のＴＡＳＫ構文で囲まれた未実行の命令コード「ｃａｌｌ  ｔｒａｖｅｒｓｅ（Ｐ％ｌｅｆｔ）」の実行にジャンプする。スレッド＃１は、最初のＴＡＳＫ構文で囲まれた命令コードを実行した後、ＴＡＳＫ構文終了部２１５を実行する。これにより、ｔａｓｋフラグは、「−１」だけデクリメントされる。ｔａｓｋフラグのデクリメントは、最初のＴＡＳＫ構文で囲まれた命令コードを実行したスレッド＃１により実行される。スレッド＃１は、自己のスレッド番号「１」がｉｄフラグに設定されていないので、同期処理部２１６による同期処理を実行して、同期待ち（ＥＮＤ  ＳＩＮＧＬＥで待機中）となる。
【００９１】
また、同期（ＥＮＤ  ＳＩＮＧＬＥ）で待機中のスレッド＃２は、次のＴＡＳＫ構文で囲まれた未実行の命令コード「ｃａｌｌ  ｔｒａｖｅｒｓｅ（Ｐ％ｒｉｇｈｔ）」の実行にジャンプする。スレッド＃２は、次のＴＡＳＫ構文で囲まれた命令コードを実行した後、ＴＡＳＫ構文終了部２１５を実行する。これにより、ｔａｓｋフラグは、「−１」だけデクリメントされる。ｔａｓｋフラグのデクリメントは、次のＴＡＳＫ構文で囲まれた命令コードを実行したスレッド＃２により実行される。スレッド＃２は、自己のスレッド番号「２」がｉｄフラグに設定されていないので、同期処理部２１６による同期処理を実行して、同期待ち（ＥＮＤ  ＳＩＮＧＬＥで待機中）となる。
【００９２】
なお、前述したように、ｉｄフラグは、ｔａｓｋフラグのリセットに応じて、リセットされる（換言すれば、「−１」とされる）。ｉｄフラグのリセットは、スレッド＃０、換言すれば、ｉｄフラグで示されるスレッド１１により実行される。
【００９３】
以上により、スレッド＃０は、「ＥＮＤ  ＳＵＢＲＯＵＴＩＮＥ」の実行後に、同期待ち（ＥＮＤ  ＳＩＮＧＬＥで待機中）となる。しかし、この時点で、ｉｄフラグの値が「０」であるので、スレッド＃０は、実際には、同期処理を実行しない、換言すれば、バリアフラグをストアしない。なお、スレッド＃０から他のスレッド１１へのバリアフラグのロードは実行される。この時、スレッド＃０のバリアフラグはストアされていない、換言すれば、未設定である。具体的には、スレッド＃０のバリアフラグは、例えば「０」である。従って、スレッド＃０からバリアフラグをロードした他のスレッド１１においても、同期は成立しない。
【００９４】
この後、スレッド＃１及び＃２がｔａｓｋフラグをデクリメントすると、ｔａｓｋフラグの値が「０」とされる。これに応じて、同期待ち（ＥＮＤ  ＳＩＮＧＬＥで待機中）であるスレッド＃０は、ｉｄフラグをリセットする。この結果、スレッド＃０は、同期を待つ処理を停止し、同期処理を実行する、換言すれば、バリアフラグをストアする。これにより、前述したように、カスケード方式に従ってバリアフラグのストアとロードを繰り返すことにより、同期が成立する。
【００９５】
なお、スレッド＃２のジャンプと共にｔａｓｋフラグがインクリメントされる前に、スレッド＃１がｔａｓｋフラグをデクリメントした場合には、ｉｄフラグは、直ちにはリセットされない。換言すれば、スレッド＃０が、同期処理部２１６による同期処理を実行して、同期待ち（ＥＮＤ  ＳＩＮＧＬＥで待機中）となった際に、ｉｄフラグをリセットする。
【００９６】
更に、スレッド＃０が「ＥＮＤ  ＳＵＢＲＯＵＴＩＮＥ」を実行する前に、スレッド＃１及び＃２がｔａｓｋフラグをデクリメントした場合にも、ｉｄフラグは、直ちにはリセットされない。換言すれば、スレッド＃０が、同期処理部２１６による同期処理を実行して、同期待ち（ＥＮＤ  ＳＩＮＧＬＥで待機中）となった際に、ｉｄフラグをリセットする。
【００９７】
図４及び図５は、スレッド処理の一例を示す図である。図４及び図５の例は、ｔａｓｋフラグが、デクリメントされることなく、繰り返しインクリメントされた結果、「５」となった場合の例、換言すれば、並列化の程度が高い場合の例である。
【００９８】
図４及び図５において、スレッド１１の数Ｎは５であり、５個のスレッド＃０〜＃４が用いられるものとする。前述したように、カスケード方式の同期においては、各スレッド１１がｌｏｇ２Ｎ回（小数点以下繰上げ）のバリアフラグのロード及び／又はストアを繰り返す。従って、同期には、３個のバリアフラグを１組として５個使用する。５個のスレッド＃０〜＃４に対応する５個のバリアフラグ領域２１３を、各々、同期領域＃０〜＃４とする。５個のバリアフラグ領域２１３は、各々、３個のバリアフラグを設定することができるようにされる。
【００９９】
図４に示すように、例えば、スレッド＃０におけるＴＡＳＫ構文指示行の検出により、ｔａｓｋフラグ領域におけるｔａｓｋフラグが「１」とされ、ｉｄフラグ領域２１２におけるｉｄフラグが当該スレッド＃０のスレッド番号「０」とされる。一方、ＴＡＳＫ構文指示行の検出に応じて、同期（ＥＮＤ  ＳＩＮＧＬＥ）で待機中のスレッド＃１が、当該ＴＡＳＫ構文で囲まれた未実行の命令コードの実行にジャンプする。
【０１００】
この後、スレッド＃１において、更に、ＴＡＳＫ構文指示行が検出されると、ｔａｓｋフラグが「２」とされる一方、ｉｄフラグは更新されない。一方、ＴＡＳＫ構文指示行の検出に応じて、同期（ＥＮＤ  ＳＩＮＧＬＥ）で待機中のスレッド＃２が、当該ＴＡＳＫ構文で囲まれた未実行の命令コードの実行にジャンプする。
【０１０１】
更に、スレッド＃２〜＃４において、ＴＡＳＫ構文指示行が検出される。このようなＴＡＳＫ構文の検出の繰り返しの結果、ｔａｓｋフラグは、繰り返しインクリメントされて「５」となる。一方、ｉｄフラグは、更新されることなく、「０」のままである。
【０１０２】
これにより、ｉｄフラグが設定された場合に、「ｉｄフラグ＝スレッド番号」が成立するスレッド＃０は、「ｔａｓｋフラグ＝０」が成立するまで、同期処理を実行しない。具体的には、図４に示すように、スレッド＃０に対応する同期領域＃０にバリアフラグを設定しない。これに対して、「ｉｄフラグ＝スレッド番号」が成立しないスレッド＃１〜＃４は、「ｔａｓｋフラグ＝０」の成立とは拘わりなく、同期処理を実行する。具体的には、図４に網掛けにより示すように、スレッド＃１〜＃４に対応する同期領域＃１〜＃４にバリアフラグを設定する。
【０１０３】
以上により、「ｔａｓｋフラグ＝０」となるまで、換言すれば、ｔａｓｋフラグがリセットされるまでｉｄフラグを更新できない。これにより、同期からのジャンプで実行される全ての未実行の命令コードが終了するまで、少なくとも１つのスレッド＃０は、同期処理を開始しない。これにより、未実行の命令コードが終了するまで、同期が成立しないことが保証される。換言すれば、未実行の命令コードとは、同期の成立までに実行される必要のある命令コードである。従って、同期の成立に必要な全ての命令コードが実行された後に、同期が成立する。
【０１０４】
なお、スレッド＃１〜＃４は、ジャンプしたプログラムの実行から復帰する都度に、ｔａｓｋフラグを「−１」だけデクリメントする。これにより、スレッド＃１〜＃４が全てジャンプしたプログラムの実行から復帰した場合には、「ｔａｓｋフラグ＝０」となるので、その後はｉｄフラグを更新することができる。
【０１０５】
また、第１の命令コードが存在しない場合には、いずれのスレッド＃０〜＃４もｉｄフラグを更新しない。一方、第１の命令コードが存在する場合には、ｉｄフラグの更新は禁止される。このため、スレッド＃０〜＃４がｉｄフラグをメインメモリ２から共有キャッシュ１４を介して各々のキャッシュ１３にロードする時に、共有キャッシュ１４におけるキャッシュ競合、換言すれば、（ｔｒｕｅ  ｓｈａｒｉｎｇ）が発生することを防止することができる。
【０１０６】
図４の状態に続いて、図５に示すように、スレッド＃０〜＃４における並列処理が、ｓｔｅｐ＃２〜ｓｔｅｐ＃６のように実行される。なお、図５において、図４の状態をｓｔｅｐ＃１として示す。  
【０１０７】
ｓｔｅｐ＃１において、スレッド＃Ｎは、同期領域Ｎのi番目のバリアフラグを設定する。ここで、変数ｉは「１」から開始される。例えば、スレッド＃１は、同期領域＃１の１番目のバリアフラグを設定する（換言すれば、ストアする）。図４においては、同期領域＃１の１番目のバリアフラグの設定が、同期領域＃１の１番目の領域に網掛けにより示される。他のスレッド＃２〜＃４においても、同期領域＃２〜＃４の１番目のバリアフラグが設定される。
【０１０８】
一方、スレッド＃０は、全ての未実行の命令コードが終了していないので、同期しない。従って、スレッド＃０は、同期領域＃０の１番目のバリアフラグを設定しない。図５において、同期領域＃０の１番目のバリアフラグを設定しないことが、当該領域に網掛けをしないことにより示される。
【０１０９】
ｓｔｅｐ＃２において、スレッド＃Ｎは、同期領域「（Ｎ＋Σ２ｊ）％スレッド数」のｉ番目のバリアフラグをロードする。ここで、変数ｊは「０」から開始される。この場合、同期領域「（Ｎ＋１）％５」の1番目のバリアフラグがロードされる。例えば、スレッド＃１についての同期領域＃１の１番目のバリアフラグは、スレッド＃２についての同期領域＃２の１番目の領域にロードされる。
【０１１０】
スレッド＃Ｎは、ｓｔｅｐ＃２においてロードしたバリアフラグが設定済みの場合、変数ｉをインクリメントしてｓｔｅｐ＃３に進む。
【０１１１】
ｓｔｅｐ＃３において、スレッド＃Ｎは、同期領域Ｎのi番目のバリアフラグを設定する。例えば、スレッド＃２は、同期領域＃２の２番目のバリアフラグを設定する。他のスレッド＃３〜＃４においても、同期領域＃３〜＃４の２番目のバリアフラグが設定される。
【０１１２】
一方、スレッド＃０は、全ての未実行の命令コードが終了していないので、同期せず、ｓｔｅｐ＃３を実行しない。スレッド＃１は、スレッド＃０からロードしたバリアフラグが未設定なので、ｓｔｅｐ＃３を実行しない。図５において、スレッド＃０からロードしたバリアフラグが未設定であることが、ロードを示す点線を省略することにより示される。
【０１１３】
ｓｔｅｐ＃４において、スレッド＃Ｎは、同期領域「（Ｎ＋Σ２ｊ）％スレッド数」のｉ番目のバリアフラグをロードする。この場合、同期領域「（Ｎ＋２）％５」の２番目のバリアフラグがロードされる。例えば、スレッド＃２についての同期領域＃２の２番目のバリアフラグは、スレッド＃４についての同期領域＃４の２番目の領域にロードされる。
【０１１４】
スレッド＃Ｎは、ｓｔｅｐ＃４においてロードしたバリアフラグが設定済みの場合、変数ｉをインクリメントしてｓｔｅｐ＃５に進む。
【０１１５】
ｓｔｅｐ＃５において、スレッド＃Ｎは、同期領域Ｎの３番目のバリアフラグを設定する。例えば、スレッド＃４は、同期領域＃４の３番目のバリアフラグを設定する。
【０１１６】
一方、スレッド＃０は、全ての未実行の命令コードが終了していないので、同期せず、ｓｔｅｐ＃５を実行しない。スレッド＃１は、ｓｔｅｐ＃３を実行しなかったので、同期せず、ｓｔｅｐ＃５を実行しない。スレッド＃２及び＃３は、各々、スレッド＃０及び＃１からロードしたバリアフラグが未設定なので、ｓｔｅｐ＃５を実行しない。図５において、スレッド＃０及び＃１からロードしたバリアフラグが未設定であることが、ロードを示す点線を省略することにより示される。
【０１１７】
ｓｔｅｐ＃６において、スレッド＃Ｎは、同期領域「（Ｎ＋Σ２ｊ）％スレッド数」のｉ番目のバリアフラグをロードする。この場合、同期領域「（Ｎ＋４）％５」の３番目のバリアフラグがロードされる。例えば、スレッド＃４についての同期領域＃４の３番目のバリアフラグは、スレッド＃３についての同期領域＃３の３番目の領域にロードされる。
【０１１８】
以上のように、「ｉｄフラグ＝スレッド番号」の条件に適合するスレッド＃０は、同期処理の実行を開始せず、「ｔａｓｋフラグ＝０」を待つ。この間、他のスレッド＃１〜＃４は、同期の成立までに実行する必要のある処理を、各々における実行の程度は異なるが、かなり実行している。従って、スレッド＃０が全ての未実行コードの実行終了後に同期を開始した場合、同期の成立までの処理時間を短縮することができる。
【０１１９】
図６は、スレッド処理の一例を示す図である。図６は、図５におけるｓｔｅｐ＃１及びｓｔｅｐ＃２を示す。
【０１２０】
スレッド＃０は、前述したように、ＴＡＳＫ構文の検出に応じて、未実行コードにジャンプする。このため、スレッド＃０は、ｔａｓｋフラグを、メインメモリ２から共有キャッシュ１４を介して、対応するキャッシュ１３にロードする。また、スレッド＃１〜＃４は、同期処理を実行する。このため、スレッド＃１〜＃４は、各々、対応する同期領域＃１〜＃４のバリアフラグを、メインメモリ２から共有キャッシュ１４を介して、対応するキャッシュ１３にロードする。
【０１２１】
ここで、ｔａｓｋフラグのロードにおいて、「ｔａｓｋフラグ＝０」の場合には、第１の命令コードは存在しない。この場合、ｔａｓｋフラグのロードを実行したために、メインメモリ２及び共有キャッシュ１４へのアクセスの機会が１回無駄になる。一方、高速で同期するためには、できるだけ頻繁に同期領域をロードすることが望ましい。
【０１２２】
そこで、「ｔａｓｋフラグ＝０」の場合には、例えば、１００００００回の同期領域のロードに対して、１回のｔａｓｋフラグのロードを行う。これにより、実行可能ファイル２２に第１の命令コードが存在しない場合でも、高速で同期することができる。
【０１２３】
図７は、スレッド処理フローを示し、特に、ソースプログラム４１、換言すれば、実行可能ファイル２２に第１の命令コードが存在する場合の処理について示す。
【０１２４】
ソースプログラム４１が、スレッド１１において実行されると（ステップＳ３１）、第１の命令コード、例えばＴＡＳＫ構文指示行が検出される。これに応じて、スレッド１１は、第１の命令コード「ｃａｌｌ  ｔｒａｖｅｒｓｅ（Ｐ％ｌｅｆｔ）」を他のスレッド１１にスケジューリングし、ライブラリ２１のＴＡＳＫ構文検出部２１４を実行する。即ち、ＴＡＳＫ構文検出部２１４は、ｉｄフラグが「−１」であるか否かを調べる（ステップＳ２１）。ｉｄフラグが「−１」である場合（ステップＳ２１  Ｙｅｓ）、ＴＡＳＫ構文検出部２１４は、ｉｄフラグに当該ＴＡＳＫ構文指示行を検出したスレッド１１のスレッド番号を設定する（ステップＳ２２）。ｉｄフラグが「−１」でない場合（ステップＳ２１  Ｎｏ）、ステップＳ２２は省略される。この後、ＴＡＳＫ構文検出部２１４は、ｔａｓｋフラグを「＋１」だけインクリメントする（ステップＳ２３）。
【０１２５】
この後、ソースプログラム４１を実行していたスレッド１１は、ＴＡＳＫ構文終了行の次の命令コードを実行する（ステップＳ３２）。この後、スレッド１１は、全ての命令コードの実行を終了すると、ＢＡＲＲＩＥＲ構文「！＄ＯＭＰ  ＥＮＤ  ＳＩＮＧＬＥ」による同期待ちとなる。換言すれば、スレッド１１は、全ての未実行の命令コードの実行が終了するまで同期処理を待ち、全ての未実行の命令コードの実行が終了した後に、同期処理を実行する。
【０１２６】
図８は、スレッド処理フローを示し、特に、ソースプログラム４１、換言すれば、実行可能ファイル２２に第１の命令コードが存在しない場合の処理について示す。
【０１２７】
ソースプログラム４１が、スレッド１１において実行されるが（ステップＳ３３）、第１の命令コード、例えばＴＡＳＫ構文指示行が検出されない。従って、ライブラリ２１のＴＡＳＫ構文検出部２１４は実行されない。従って、この場合、ｔａｓｋフラグ＝０であり、ｉｄフラグは「−１」である。
【０１２８】
図９は、スレッド処理フローを示し、特に、同期処理及びＴＡＳＫ構文の終了処理について示す。
【０１２９】
同期待ち（ＥＮＤ  ＳＩＮＧＬＥで待機中）のスレッド１１は、ｉｄフラグが自己のスレッド番号であるか否かを調べる（ステップＳ４１）。ｉｄフラグが自己のスレッド番号である場合（ステップＳ４１  Ｙｅｓ）、スレッド１１は、ｔａｓｋフラグ＝０であるか否かを調べる（ステップＳ４２）。ｔａｓｋフラグ＝０でない場合（ステップＳ４２  Ｎｏ）、スレッド１１は、タスクの実行にジャンプし（ステップＳ４３）、タスクの実行の終了後にｔａｓｋフラグを「−１」だけデクリメントし（ステップＳ４４）、ステップＳ４２を繰り返す。
【０１３０】
ステップＳ４２において、ｔａｓｋフラグ＝０である場合（ステップＳ４２  Ｙｅｓ）、スレッド１１は、ｉｄフラグを「−１」にリセットする（ステップＳ４５）。
【０１３１】
ステップＳ４１において、ｉｄフラグが自己のスレッド番号でない場合（ステップＳ４１  Ｎｏ）、ステップＳ４２及びＳ４５は省略される。
【０１３２】
この後、スレッド１１は、同期領域のi番目のバリアフラグを設定する変数ｉを「１」に設定し（ステップＳ４６）、ｔａｓｋフラグ＝０であるか否かを調べる（ステップＳ４７）。ｔａｓｋフラグ＝０でない場合（ステップＳ４７  Ｎｏ）、スレッド１１は、タスクの実行にジャンプし（ステップＳ４８）、タスクの実行の終了後にｔａｓｋフラグを「−１」だけデクリメントし（ステップＳ４９）、ステップＳ４７を繰り返す。
【０１３３】
ステップＳ４７において、ｔａｓｋフラグ＝０である場合（ステップＳ４７  Ｙｅｓ）、スレッド１１は、変数ｉを「＋１」だけインクリメントし（ステップＳ４１０）、同期領域にバリアフラグが設定されたか否かを調べる（ステップＳ４１１）。
【０１３４】
同期領域にバリアフラグが設定されていない場合（ステップＳ４１１  Ｎｏ）、スレッド１１は、変数ｉがスレッド１１の数Ｎと等しいか否かを調べる（ステップＳ４１２）。変数ｉがスレッド１１の数Ｎと等しくない場合（ステップＳ４１２  Ｎｏ）、スレッド１１は、ステップＳ４１０を繰り返す。変数ｉがスレッド１１の数Ｎと等しい場合（ステップＳ４１２  Ｙｅｓ）、スレッド１１は、ステップＳ４６を繰り返す。
【０１３５】
ステップＳ４１１において、同期領域にバリアフラグが設定された場合（ステップＳ４１１  Ｙｅｓ）、同期が成立しているので、スレッド１１は、ＴＡＳＫ構文終了行の次の命令コードを実行する。
【符号の説明】
【０１３６】
１    ＣＰＵ
１１    スレッド
１２    ＣＰＵコア
１３    キャッシュ
１４    共用キャッシュ
２    メインメモリ
２１    ライブラリ
２２    実行可能ファイル
２１１    ｔａｓｋフラグ領域
２１２    ｉｄフラグ領域
２１３    バリアフラグ領域
【図１】
0005504879.tif 000002
【図２】
0005504879.tif 000003
【図３】
0005504879.tif 000004
【図４】
0005504879.tif 000005
【図５】
0005504879.tif 000006
【図６】
0005504879.tif 000007
【図７】
0005504879.tif 000008
【図８】
0005504879.tif 000009
【図９】
0005504879.tif 000010
【図１０】
0005504879.tif 000011
【図１１】
0005504879.tif 000012
【図１２】
0005504879.tif 000013
【図１３】
0005504879.tif 000014