(57)【特許請求の範囲】
【請求項１】
処理すべきデータ集合の要素数から、スレッド数よりも大きい前記データ集合の分割数を算出し、
算出した分割数に、前記データ集合を分割し、
分割したデータ集合それぞれの処理を行う複数の実行コードを含み、各実行コードの先頭に、該実行コードに最初に到達したスレッドが処理を行う命令を配してあるオブジェクトコードを生成する処理をコンピュータに行わせる
コンパイラプログラム。
【請求項２】
処理すべきデータ集合の要素数から算出した、スレッド数よりも大きい分割数で前記データ集合を分割した部分集合それぞれを処理する複数の実行コードを含み、各実行コードの先頭に、該実行コードに最初に到達したスレッドが処理を行う命令が配してあり、
前記スレッド数のスレッドで、前記複数の実行コードの処理を並列的にコンピュータに行わせる
コンピュータプログラム。
【請求項３】
処理すべきデータ集合の要素数から、スレッド数よりも大きい前記データ集合の分割数を算出する算出部と、
算出した分割数に、前記データ集合を分割する分割部と、
分割したデータ集合の処理を行う複数の実行部、及び各実行部に最初に到達したスレッドが行う命令を、各実行部の先頭に配してあるオブジェクトコードを生成する生成部とを備える
コンパイラ装置。
【発明の詳細な説明】
【技術分野】
【０００１】
本発明は、並列処理を行うコンピュータプログラム、コンピュータプログラムを生成するコンピュータプログラム及びコンパイラ装置に関する。
【背景技術】
【０００２】
従来から、マルチプロセッサ計算機に並列処理を実行させるオブジェクトコードを、ソースコードから生成するコンパイラプログラムが知られている（特許文献１、特許文献２）。
【先行技術文献】
【特許文献】
【０００３】
【特許文献１】特開平５−１２０３３号公報
【特許文献２】特開平５−６１８９９号公報
【発明の概要】
【発明が解決しようとする課題】
【０００４】
大量のデータを複数スレッドで並列処理する場合、処理データをスレッド数よりも多くの部分集合に分割しておき、データの各部分集合に対する処理をメモリ上に配置し、各スレッドが割当分を終了したときに次の部分集合を割り当てるようにする。このような処理では、次の部分集合を割り当てる際に、各部分集合が「未処理」、「処理済み」、「他のスレッドに割当済」のいずれの状態であるかを確定するための同期処理が必要となる。この同期処理は、処理全体から見ればオーバヘッドとなる。さらに、同期処理の回数が増えれば、データ処理時間が短縮しても、同期処理のオーバヘッドにより、全体の処理時間が結果的に短縮されない。
【０００５】
１つの側面では、複数スレッドでデータを処理する際の実行時間を短縮させるオブジェクトプログラムを生成するコンパイラプログラム等を提供することを目的とする。
【課題を解決するための手段】
【０００６】
本明細書に開示するコンパイラプログラムは、処理すべきデータ集合の要素数から、スレッド数よりも大きい前記データ集合の分割数を算出し、算出した分割数に、前記データ集合を分割し、分割したデータ集合それぞれの処理を行う複数の実行コードを含み、各実行コードの先頭に、該実行コードに最初に到達したスレッドが処理を行う命令を配してあるオブジェクトコードを生成する処理をコンピュータに行わせる。
【発明の効果】
【０００７】
本発明の一観点によれば、複数スレッドでデータを処理する際の全体の処理時間を短縮することが可能となる。
【図面の簡単な説明】
【０００８】
【図１】コンパイラ装置のハードウェア構成の一例を示すブロック図である。
【図２】並列処理装置のハードウェア構成の一例を示すブロック図である。
【図３】並列処理プログラムの構造の一例を示す説明図である。
【図４】並列処理装置の備えるＣＰＵの構成の一例を示すブロック図である。
【図５】ＳＡ命令の動作内容をフローチャートである。
【図６】命令コードＴＥＳＴ＆ＩＤＡにより実行される処理の例を示すフローチャートである。
【図７】ＳＡ命令の動作例を示す説明図である。
【図８】並列処理プログラムの生成手順を示すフローチャートである。
【図９】部分実行部の生成手順を示すフローチャートである。
【図１０】部分実行部の出力手順を示すフローチャートである。
【図１１】部分実行部の構成の一例を示す説明図である。
【図１２】並列処理プログラムの構成の一例を示す説明図である。
【図１３】部分実行部の内容を示す説明図である。
【図１４】並列処理プログラムの生成手順を示すフローチャートである。
【図１５】並列処理プログラムの構成の一例を示す説明図である。
【図１６】並列処理プログラムの構成の一例を示す説明図である。
【図１７】コンパイラ装置の機能構成の一例を示す説明図である。
【発明を実施するための形態】
【０００９】
実施の形態１
以下、実施の形態を、図面を参照して説明する。図１はコンパイラ装置１のハードウェア構成の一例を示すブロック図である。コンパイラ装置１は、汎用コンピュータ、ワークステーション、デスクトップ型ＰＣ（パーソナルコンピュータ）、ノートブック型ＰＣ等である。コンパイラ装置１は、ＣＰＵ（Ｃｅｎｔｒａｌ  Ｐｒｏｃｅｓｓｉｎｇ  Ｕｎｉｔ）１１、ＲＡＭ（Ｒａｎｄｏｍ  Ａｃｃｅｓｓ  Ｍｅｍｏｒｙ）１２、ＲＯＭ（Ｒｅａｄ  Ｏｎｌｙ  Ｍｅｍｏｒｙ）１３、大容量記憶装置１４、入力部１５、出力部１６、通信部１７、読取り部１８を含む。各構成はバスで接続されている。
【００１０】
ＣＰＵ１１はＲＯＭ１３に記憶された制御プログラム１Ｐに従いハードウェア各部を制御する。ＲＡＭ１２は例えばＳＲＡＭ（Ｓｔａｔｉｃ  ＲＡＭ）、ＤＲＡＭ（Ｄｙｎａｍｉｃ  ＲＡＭ）、フラッシュメモリである。ＲＡＭ１２はＣＰＵ１１によるプログラムの実行時に発生するデータを一時的に記憶する。
【００１１】
大容量記憶装置１４は、例えばハードディスク、ＳＳＤ（Ｓｏｌｉｄ  Ｓｔａｔｅ  Ｄｒｉｖｅ）などである。大容量記憶装置１４には、各種データが記憶されている。また、制御プログラム１Ｐを大容量記憶装置１４に記憶するようにしておいても良い。
【００１２】
入力部１５はコンパイラ装置１にデータを入力するためのキーボート、マウスなどを含む。
【００１３】
出力部１６は画像出力を行う表示装置、音声出力を行うスピーカなどを含む。
【００１４】
通信部１７はネットワークを介して、他のコンピュータと通信を行う。読取り部１８はＣＤ（Ｃｏｍｐａｃｔ  Ｄｉｓｃ）−ＲＯＭ、ＤＶＤ（Ｄｉｇｉｔａｌ  Ｖｅｒｓａｔｉｌｅ  Ｄｉｓｃ）−ＲＯＭを含む可搬型記憶媒体１ａを読み取る。ＣＰＵ１１が読取り部１８を介して、制御プログラム１Ｐを可搬型記憶媒体１ａより読み取り、大容量記憶装置１４に記憶しても良い。また、ネットワークを介して他のコンピュータからＣＰＵ１１が制御プログラム１Ｐをダウンロードし、大容量記憶装置１４に記憶しても良い。さらにまた、半導体メモリ１ｂから、ＣＰＵ１１が制御プログラム１Ｐを読み込んでも良い。
【００１５】
図２は並列処理装置２のハードウェア構成の一例を示すブロック図である。並列処理装置２は、汎用コンピュータ、ワークステーション、デスクトップ型ＰＣ、ノートブック型ＰＣ等である。並列処理装置２は、ＣＰＵ２１、ＲＡＭ２２、ＲＯＭ２３、大容量記憶装置２４、入力部２５、出力部２６、通信部２７、読取り部２８を含む。各構成はバスで接続されている。並列処理装置２のハードウェアの各構成は、コンパイラ装置１と同様であるので、説明を省略する。
【００１６】
コンパイラ装置１はコンパイラプログラムを実行し、ソースコードから並列処理装置２で実行可能な並列処理プログラム（オブジェクトコード）を生成する。並列処理装置２でコンパイラプログラムを実行し、並列処理プログラムを生成してもよい。
【００１７】
本実施の形態における並列処理プログラムは、処理すべきデータの集合を所定数に分割し、分割された部分集合毎に処理ブロックが設けられていることを特徴とする。図３は並列処理プログラムの構造の一例を示す説明図である。並列処理プログラムは、処理すべきデータを部分集合に分割し、分割した各部分集合を処理する処理ブロック（実行コード）を含む。図３では、部分集合１に対する処理を行う処理ブロック１、部分集合２に対する処理を行う処理ブロック２、部分集合３に対する処理を行う処理ブロック３、部分集合４に対する処理を行う処理ブロック４が示されている。各処理ブロックの先頭には、条件分岐命令（以下「ＳＡ命令」と呼ぶ）が埋め込まれている。ＳＡ命令については、後述する。
【００１８】
図４は、並列処理装置２の備えるＣＰＵ２１の構成の一例を示すブロック図である。ＣＰＵ２１は、複数のコアＣ（Ｃ０、Ｃ１、Ｃ２、Ｃ３）、キャッシュメモリＣＭおよびレジスタ部ＲＥＧＵを有する。コアＣは、互いに同一または同様の構成であるため、図３では、コアＣ０の構成を示し、以下では、コアＣ０の構成を説明する。なお、コアＣの数は、４つに限定されない。ＣＰＵ２１は、ＲＡＭ２２に接続される。
【００１９】
コアＣ０は、演算部ＯＰＵ、データレジスタ部ＤＲＥＧ、アドレスレジスタ部ＡＲＥＧ、プログラムカウンタＰＣ、インクリメンタＩＮＣ、命令レジスタ部ＩＲＥＧ、デコーダ部ＤＥＣおよびセレクタＳ１、Ｓ２を有する。演算部ＯＰＵは、レジスタファイルＲＥＧ、演算器ＥＸおよびフラグレジスタＳＦ、ＺＦを有する。
【００２０】
プログラムカウンタＰＣは、セレクタＳ１から受けるアドレスをインクリメンタＩＮＣおよびセレクタＳ２に出力する。インクリメンタＩＮＣは、プログラムカウンタＰＣから受けるアドレスをインクリメントし、インクリメントしたアドレスをセレクタＳ１に出力する。
【００２１】
セレクタＳ１は、命令コードを順次にフェッチする場合、インクリメンタＩＮＣからの
アドレスを選択し、分岐命令またはジャンプ命令等が実行される場合、演算部ＯＰＵからのアドレスを選択する。そして、セレクタＳ１は、選択したアドレスをプログラムカウンタＰＣに出力する。セレクタＳ２は、命令コードをフェッチする場合、プログラムカウンタＰＣから出力されるアドレスを選択し、ロード命令またはストア命令を実行する場合、アドレスレジスタ部ＡＲＥＧから出力されるアドレスを選択する。そして、セレクタＳ２は、選択したアドレスを、アドレスバスＡＤ０を介してキャッシュメモリＣＭに出力する。
【００２２】
コアＣ０が命令をフェッチする場合、アドレスＡＤ０に応じて、キャッシュメモリＣＭから命令コードが読み出され、読み出された命令コードがデータバスＤＩＮを介して命令レジスタ部ＩＲＥＧに格納される。キャッシュメモリＣＭが命令コードを保持していない場合、キャッシュメモリＣＭは、アドレスバスＡＤ１を介してＲＡＭ１２にアドレスを出力し、データバスＤＴを介してＲＡＭ１２から命令コードを受ける。例えば、アドレスＡＤ１は、アドレスＡＤ０の上位アドレスであり、キャッシュメモリＣＭの１キャッシュライン分の命令コード（プログラム）がＲＡＭ１２から読み出される。そして、キャッシュメモリＣＭは、ＲＡＭ１２から読み出した命令コードを保持するとともに、保持した命令コードのうち読み出し対象の命令コードを、データバスＤＩＮを介して命令レジスタ部ＩＲＥＧに出力する。
【００２３】
コアＣ０がロード命令を実行する場合、アドレスＡＤ０に応じて、キャッシュメモリＣＭからデータが読み出され、読み出されたデータがデータバスＤＩＮを介してレジスタファイルＲＥＧに格納される。キャッシュメモリＣＭがロード命令の対象のデータを保持していない場合、命令コードの読み出しと同様に、キャッシュメモリＣＭは、ＲＡＭ２２から１キャッシュライン分のデータを読み出す。そして、キャッシュメモリＣＭは、ＲＡＭ２２から読み出したデータを保持するとともに、保持したデータのうちロード対象のデータを、データバスＤＩＮを介してレジスタファイルＲＥＧに出力する。
【００２４】
コアＣ０がストア命令を実行する場合、アドレスバスＡＤ０に出力されたアドレスに応じて、データレジスタ部ＤＲＥＧからデータバスＤＯＵＴに出力されたデータがキャッシュメモリＣＭに書き込まれる。
【００２５】
命令レジスタ部ＩＲＥＧは、キャッシュメモリＣＭから受ける命令コードを保持する複数の領域を有し、保持している命令コードをデコーダ部ＤＥＣに順次に出力する。デコーダ部ＤＥＣは、命令レジスタ部ＩＲＥＧから受ける命令コードをデコードし、デコード結果に基づいて、演算部ＯＰＵおよびセレクタＳ１、Ｓ２等の動作を制御する制御信号を生成する。
【００２６】
データレジスタ部ＤＲＥＧは、ストア命令の実行時に演算部ＯＰＵから出力されるデータを保持する複数の領域を有する。アドレスレジスタ部ＡＲＥＧは、ロード命令またはストア命令の実行時に演算部ＯＰＵから出力されるアドレスを保持する複数の領域を有する。
【００２７】
レジスタファイルＲＥＧは、キャッシュメモリＣＭから読み出されるデータまたは演算器ＥＸから出力されるデータを保持する複数のレジスタを有する。レジスタファイルＲＥＧは、デコーダ部ＤＥＣからの制御信号に基づいて、レジスタファイルＲＥＧの複数のレジスタの少なくともいずれかに保持しているデータを演算器ＥＸに出力する。
【００２８】
演算器ＥＸは、デコーダ部ＤＥＣがデコードした命令コードにしたがって演算を実行し、演算結果をレジスタファイルＲＥＧ、データレジスタ部ＤＲＥＧ、アドレスレジスタ部ＡＲＥＧまたはセレクタＳ１に出力する。また、演算器ＥＸは、演算結果に基づいてフラグレジスタＳＦ、ＺＦをセットまたはリセットし、論理演算命令または分岐命令等を実行する場合にフラグレジスタＳＦ、ＺＦの値を参照する。なお、演算部ＯＰＵは、フラグレジスタＳＦ、ＺＦ以外のフラグレジスタを有してもよい。
【００２９】
レジスタ部ＲＥＧＵは、複数のレジスタＲＥＧｉ（ｉは０、１、２、３、４のいずれか）と、レジスタＲＥＧｊとを有する。なお、レジスタＲＥＧｉの記憶領域の数Ｉは、”５”に限定されず、”１”以上であればよい。レジスタ部ＲＥＧＵは、コアＣ０−Ｃ３の各々が実行する処理が、各処理ブロックの入口へ到達したことを示す到達情報を保持する。
【００３０】
図３では、各レジスタＲＥＧｉに保持される値は、符号Ｘｉ（Ｘ０からＸ４のいずれか）で示される。例えば、各レジスタＲＥＧｉのビット幅とレジスタＲＥＧｊのビット幅とは、互いに等しい。
【００３１】
レジスタＲＥＧｉは、並列処理の進行とともに、巡回的に使用される。各レジスタＲＥＧｉには、各部分集合の処理を行う各処理ブロックの入口に到達していないスレッドＴＨの数である未到達数Ｘｉが格納される。なお、コアＣ０−Ｃ３の数（＝４）から未到達数Ｘｉを減じた値は、各処理ブロックの入口に到達したスレッドＴＨの数を示す。すなわち、未到達数Ｘｉは、各処理ブロックの入口に処理が到達したコアＣ０−Ｃ３の数を示す到達数情報の一例である。なお、各レジスタＲＥＧｉには、各処理ブロックの入口に到達したスレッドＴＨの数が格納されてもよい。
【００３２】
レジスタＲＥＧｊには、全てのスレッドＴＨが通過したシングル処理ブロックＳＩＢの総数である総通過数ｊが格納される。総通過数ｊは、全てのコアＣ０−Ｃ３の処理が通過したシングル処理ブロックＳＩＢの数を示す総通過数情報の一例である。レジスタＲＥＧｊは、総通過数情報を保持する総通過数領域の一例である。
【００３３】
命令コードＴＥＳＴ＆ＩＤＡは、加算命令、乗算命令、ロード命令、ストア命令などと同様に、演算器ＥＸがマイクロプログラムを実行することで処理される。なお、命令コードＴＥＳＴ＆ＩＤＡを実行する演算器ＥＸの動作は、ワイヤードロジックで実現されてもよい。しかしながら、マイクロプログラム方式を採用することで、命令コードＴＥＳＴ＆ＩＤＡを、ワイヤードロジック方式に比べて容易に追加することができ、ハードウェア機能（命令セットのアーキテクチャ）を容易に変更することができる。
【００３４】
キャッシュメモリＣＭは、命令キャッシュおよびデータキャッシュとして動作する。なお、キャッシュメモリＣＭは、コアＣ毎に設けられてもよく、一次キャッシュおよび二次キャッシュを含んでもよい。ＲＡＭ２２には、コアＣにより実行されるスレッド数数ｎを保持する記憶領域と、コアＣ０−Ｃ３のそれぞれが各処理ブロックを通過した数を示す通過数ｍ（ｍ０、ｍ１、ｍ２、ｍ３）を保持する記憶領域とを設ける。スレッド数ｎおよび通過数ｍは、キャッシュメモリＣＭにも保持される。キャッシュメモリＣＭがスレッド数ｎおよび通過数ｍを保持する場合、各コアは、ＲＡＭ２２にアクセスすることなく、キャッシュメモリＣＭにアクセスすることで、スレッド数ｎおよび通過数ｍを参照することができ、また、通過数ｍを書き替えることができる。
【００３５】
次に、ＳＡ命令について説明する。ＳＡ命令は、レジスタ部ＲＥＧＵに保持された未到達数Ｘｉおよび総通過数ｊに基づき、ＮＯＰ命令又はＪｕｍｐ命令として動作する。ＳＡ命令は２つの引数ｎ、ａｄｒを取る。ｎはスレッド数である。ａｄｒはＪｕｍｐ命令として動作するときのジャンプ先アドレスである。
【００３６】
図５はＳＡ命令の動作内容をフローチャートである。コアＣはスレッド数ｎおよび通過数ｍをＲＡＭ１２からロードする（ステップＳ１１）。ＲＡＭ１２がスレッド数ｎおよび通過数ｍを保持している場合、スレッド数ｎおよび通過数ｍは、キャッシュメモリＣＭから読み出される。
【００３７】
次に、コアＣは、ＲＡＭ１２からロードしたスレッド数ｎおよび通過数ｍを変数として、命令コードＴＥＳＴ＆ＩＤＡを実行する（ステップＳ１２）。コアＣはフラグレジスタＳＦの値が１であるか否かを判定する（ステップＳ１３）。コアＣはフラグレジスタＳＦの値が１と判定した場合（ステップＳ１３でＹＥＳ）、レジスタＲＥＧｉに空きがあると判断し、フラグレジスタＺＦの値が１であるか否かを判定する（ステップＳ１５）。コアＣはフラグレジスタＳＦの値が１でないと判定した場合（ステップＳ１３でＮＯ）、レジスタＲＥＧｉに空きがないと判断し、処理をステップＳ１４に移す。コアＣは所定時間を待った後、処理をステップＳ１２に戻す。なお、ステップＳ１４において、コアＣは、所定時間を待つ間、他の処理を実行してもよい。
【００３８】
コアＣはフラグレジスタＺＦの値が１であると判定した場合（ステップＳ１５でＹＥＳ）、ＰＣ（プログラムカウンタ）をＳＡ命令の次のアドレスに設定する（ステップＳ１６）。コアＣはフラグレジスタＺＦの値が１でないと判定した場合（ステップＳ１５でＮＯ）、ＰＣ（プログラムカウンタ）をａｄｒに設定する（ステップＳ１７）。
【００３９】
コアＣはＲＡＭ１２からロードした通過数ｍを１増加させる（ステップＳ１８）。コアＣは通過数ｍをＲＡＭ１２にストアする（ステップＳ１９）。キャッシュメモリＣＭが通過数ｍを保持している場合、通過数ｍは、キャッシュメモリＣＭに保持された後、ＲＡＭ１２に格納される。そして、コアＣはＳＡ命令の実行を終了する。
【００４０】
図６は命令コードＴＥＳＴ＆ＩＤＡにより実行される処理の例を示す。図６に示す処理は、図４に示す演算器ＥＸが、命令コードＴＥＳＴ＆ＩＤＡに対応するマイクロプログラムを実行することで実現される。
【００４１】
演算器ＥＸは、通過数ｍと総通過数ｊとの差がレジスタＲＥＧｉの数Ｉより小さいか否かを判定する（ステップＳ２１）。演算器ＥＸは、通過数ｍと総通過数ｊとの差がレジスタＲＥＧｉの数Ｉより小さいと判定した場合（ステップＳ２１でＹＥＳ）、各処理ブロックの入口へ処理が到達したことを示すために、フラグレジスタＳＦを１にセットする（ステップＳ２２）。
【００４２】
演算器ＥＸは、通過数ｍをレジスタＲＥＧｉの数Ｉで除した余りｉを算出し、算出した余りｉを、使用するレジスタＲＥＧｉの番号ｉとする（ステップＳ２３）。
【００４３】
演算器ＥＸは、ステップＳ２３で求めたレジスタＲＥＧｉに格納された未到達数Ｘｉが０であるか否か、すなわち、最初に処理ブロックの入口へ処理が到達したか否かを判定する（ステップＳ２４）。演算器ＥＸは、最初に処理ブロックの入口へ処理が到達した判定した場合、すなわち、Ｘｉが０であると判定した場合（ステップＳ２４でＹＥＳ）、スレッド数ｎから１を引いた値を、未到達数ＸｉとしてレジスタＲＥＧｉに格納する（ステップＳ２５）。演算器ＥＸは、処理ブロックの入口へ処理が最初に到達したことを示すために、フラグレジスタＺＦを１にセットし（ステップＳ２６）、処理を終了する。
【００４４】
一方、演算器ＥＸは、未到達数Ｘｉが０でないと判定した場合（ステップＳ２４でＮＯ）、他のコアＣの処理が処理ブロックの入口へ到達済みであるので、未到達数Ｘｉを１減らす（ステップＳ２７）。演算器ＥＸは、処理ブロックの入口へ処理が最初に到達していないことを示すために、フラグレジスタＺＦを０にリセットする（ステップＳ２８）。演算器ＥＸは、未到達数Ｘｉが０であるか否かを判定する（ステップＳ２９）。演算器ＥＸは、未到達数Ｘｉが０の場合（ステップＳ２９でＹＥＳ）、処理ブロックの入口への処理の到達が最後であるので、総通過数ｊを１増加させ（ステップＳ３０）、処理を終了する。
【００４５】
演算器ＥＸは、未到達数Ｘｉが０でない場合（ステップＳ２９でＮＯ）、処理ブロックの入口へ処理が到達していない他のコアＣがあるので、処理を終了する。
【００４６】
一方、演算器ＥＸは、通過数ｍと総通過数ｊとの差がレジスタＲＥＧｉの数Ｉ以上であると判定した場合（ステップＳ２１でＮＯ）、すなわち、使用可能なレジスタＲＥＧｉがない場合、フラグレジスタＳＦを０にセットし（ステップＳ３１）、処理を終了する。フラグレジスタＳＦを０にセットするのは、処理ブロックの入口へ処理が実際には到達しているが、到達していないことを擬似的に示すためである。
【００４７】
以上のように、ＳＡ命令により、各処理ブロックの入口へ処理が最初に到達したスレッドが、処理ブロックの処理を実行し、各処理ブロックの入口へ処理が２番目以降に到達したスレッドは、次の処理ブロックの入口へジャンプする。それにより、各処理ブロックの入口へ処理が最初に到達したスレッドが、各処理ブロックを実行する。各処理ブロックの入口へ処理が２番目以降に到達したスレッドは、次の処理ブロックの入口へジャンプする。したがって、同期処理をせずに、各スレッドは未処理の部分集合に関する処理を連続して実行することが可能となる。
【００４８】
次に、ＳＡ命令の動作例を示す。図７はＳＡ命令の動作例を示す説明図である。図７に示す例では簡単のために２つのスレッド１、２が動作する場合を示している。スレッド１、２は、図７の上部から下部に向かって処理を行う。時刻Ｔ１において、スレッド１は処理ブロック１の入口に到達し、ＳＡ命令を実行する。スレッド２は時刻Ｔ１の時点では、処理ブロックの入口へ到達はしていないので、スレッド１の実行したＳＡ命令はＮＯＰと同様な処理を行い、スレッド１が処理ブロック１の処理を行う。
【００４９】
時刻Ｔ２にスレッド２が処理ブロック２の入口に到達する。スレッド２がＳＡ命令を実行すると、２番目以降の到達であるからジャンプ命令の動作となり、処理ブロック２の入口へジャンプする。スレッド２は再び、ＳＡ命令を実行する。スレッド１は時刻Ｔ２では処理ブロック１の実行を行っている。したがって、スレッド２が処理ブロック２の入口へ到達したスレッドであるから、ＳＡ命令はＮＯＰと同様な処理となり、スレッド２が処理ブロック２の処理を行う。
【００５０】
時刻Ｔ３にスレッド１が処理ブロック２の入口へ到達するが、すでにスレッド２が到達済みであるから、ＳＡ命令の実行により、スレッド１は処理ブロック３の入口へジャンプする。再び、スレッド１はＳＡ命令を実行する。時刻Ｔ３において、スレッド２は処理ブロック２を実行中であるから、スレッド１が処理ブロック３の入口へ最初に到達したスレッドである。したがってＳＡ命令はＮＯＰと同様な処理となり、スレッド１が処理ブロック３の処理を行う。
【００５１】
時刻Ｔ４にスレッド１が処理ブロック４の入口へ到達する。スレッド１がＳＡ命令を実行する。スレッド２は処理ブロック２の処理を行っているため、スレッド１が処理ブロック４の入口に最初に到達したスレッドである。したがってＳＡ命令はＮＯＰと同様な処理となり、スレッド１が処理ブロック４の処理を行う。
【００５２】
次に、ＳＡ命令を用いた並列処理プログラムを生成するコンパイラについて説明する。コンパイラ装置１のＣＰＵ１１がコンパライラプログラムを実行することにより、ＣＰＵ１１はコンパイラとして動作する。ここでは一例として、以下に示す処理対象コードＤに含まれる処理対象データの集合Ｓを、ｋ個のスレッドで並列処理させるオブジェクトプログラム（並列処理プログラム）を生成するものとする。
【００５３】
＜Ｓの宣言部＞
ｔｈｒｅａｄ＿ｐａｒａｌｌｅｌ＿ｓｔａｒｔ
＜Ｓに対する並列処理実行部＞
ｔｈｒｅａｄ＿ｐａｒａｌｌｅｌ＿ｅｎｄ
【００５４】
図８は並列処理プログラムの生成手順を示すフローチャートである。ＣＰＵ１１は、集合（データ集合）Ｓを０からｎ−１の指標で指定されるｎ個の部分集合に分割するために、ｎ≧ｋの条件を満たす分割数ｎを、次のように定める。ＣＰＵ１１は、集合Ｓの要素数｜Ｓ｜をｋで除した値が閾値Ａより大きいか否かを、判定する（ステップＳ４１）。なお、閾値Ａは、並列処理プログラムを生成するのに先立ち、すなわち、コンパイル実行時に与えられるものとする。ＣＰＵ１１は、要素数｜Ｓ｜をｋで除した値が閾値Ａより大きいと判定した場合（ステップＳ４１でＹＥＳ）、分割数ｎを、スレッドの個数ｋを３倍にした値とする（ステップＳ４２）。ＣＰＵ１１は、要素数｜Ｓ｜をｋで除した値が閾値Ａ以下であると判定した場合（ステップＳ４１でＮＯ）、分割数ｎをステップの個数ｋとする（ステップＳ４３）。ＣＰＵ１１は、分割数ｎの数だけ、部分実行部（実行コード、処理ブロック）を生成する（ステップＳ４４）。部分実行部とは、並列処理実行部の処理内容と、ｎ分割された集合Ｓの部分集合の１つとが対応付けられたものである。ＣＰＵ１１は、生成した部分実行部を出力する（ステップＳ４５）。ＣＰＵ１１は並列処理プログラムの生成を終了する。
【００５５】
図９は部分実行部の生成手順を示すフローチャートである。ＣＰＵ１１はループ変数ｉを０に設定する（ステップＳ５１）。ＣＰＵ１１は集合Ｓの要素数｜Ｓ｜をｎで割った余り（｜Ｓ｜％ｎ）がｉより大きいか否かを判定する（ステップＳ５２）。ＣＰＵ１１は要素数｜Ｓ｜をｎで割った余り（｜Ｓ｜％ｎ）がｉより大きいと判定した場合（ステップＳ５２でＹＥＳ）、要素数｜ｓ｜をｎで除した値に１足したものをｉｔｅｒ［ｉ］に設定する（ステップＳ５３）。ＣＰＵ１１は要素数｜Ｓ｜をｎで割った余り（｜Ｓ｜％ｎ）がｉより大きくないと判定した場合（ステップＳ５２でＮＯ）、要素数｜ｓ｜をｎで除した値に設定する（ステップＳ５４）。ｉｔｅｒ［ｉ］は、ｉ番目の部分実行部での処理の繰り返し数を示す。
【００５６】
ＣＰＵ１１はループ変数ｉを１増加させる（ステップＳ５５）。ＣＰＵ１１はループ変数ｉがｎ以上となったか否かを判定する（ステップＳ５６）。ＣＰＵ１１はループ変数ｉがｎ以上ではないと判定した場合（ステップＳ５６でＮＯ）、処理をステップＳ５２へ戻す。ＣＰＵ１１はループ変数ｉがｎ以上であると判定した場合（ステップＳ５６でＹＥＳ）、ステップＳ５７以下の処理を行う。Ｓ５７以下の処理は、集合Ｓのうち各部分集合が処理を行う箇所の先頭要素番号ａｄｄ［ｉ］を設定する処理である。
【００５７】
ＣＰＵ１１は変数ｔｍｐの値を０に設定する（ステップＳ５７）。ＣＰＵ１１はａｄｄ［０］の値をｔｍｐとする（ステップＳ５８）。ＣＰＵ１１はループ変数ｉを１に設定する（ステップＳ５９）。ＣＰＵ１１は変数ｔｍｐの値に、ｉｔｅｒ［ｉ−１］の値を、新たな変数ｔｍｐの値とする（ステップＳ６０）。ＣＰＵ１１はａｄｄ［ｉ］の値を変数ｔｍｐの値とする（ステップＳ６１）。ＣＰＵ１１はループ変数ｉの値を１増加させる（ステップＳ６２）。ＣＰＵ１１はループ変数ｉがｎより大きいか否かを判定する（ステップＳ６３）。ＣＰＵ１１はループ変数ｉがｎより大きくないと判定した場合（ステップＳ６３でＮＯ）、処理をステップＳ６０に戻す。ＣＰＵ１１はループ変数ｉがｎより大きいと判定した場合（ステップＳ６３でＹＥＳ）、処理を呼び出し元に戻す。なお、説明の都合上、図９では、ステップＳ５２からＳ５４までの処理と、ステップＳ６０からステップＳ６１までの処理とを別のループとして示したが、１つのループ処理することが可能である。
【００５８】
図１０は部分実行部の出力手順を示すフローチャートである。ＣＰＵ１１はループ変数ｉを０に設定する（ステップＳ７１）。ＣＰＵ１１はＳＡ命令を出力する（ステップＳ７２）。ＳＡ命令の第１引数には、スレッド数であるｋを設定する。第２引数には、ｉ番目の部分実行部を格納するメモリアドレスの次のメモリアドレス（出口アドレス）を設定する。ＣＰＵ１１はｉ番目の部分実行部の命令群Ｑ（ｉ）を出力する（ステップＳ７３）。ＣＰＵ１１はループ変数ｉを１増加させる（ステップＳ７４）。ＣＰＵ１１はループ変数ｉがｎ以上であるか否かを判定する（ステップＳ７５）。ＣＰＵ１１はループ変数ｉがｎ以上ではないと判定した場合（ステップＳ７５でＮＯ）、処理をステップＳ７２に戻す。ＣＰＵ１１はループ変数ｉがｎ以上であると判定した場合（ステップＳ７５でＹＥＳ）、処理を呼び出し元に戻す。なお、部分実行部の出力は、図９に示す部分実行部の生成と一体の処理として、１つのループ処理として行うことも可能である。
【００５９】
図１１は部分実行部の構成の一例を示す説明図である。図１１に示すのはｉ番目の部分実行部である。上述したように、部分実行部の冒頭には、ＳＡ命令が設けられている。第１引数には、スレッド数であるｋが設定されている。第２引数には、次の（ｉ＋１）番目の部分実行部の先頭アドレスである０ｘｂｂｂｂｂｂｂｂが設定されている。
【００６０】
図１２は並列処理プログラムの構成の一例を示す説明図である。並列処理プログラムは、部分実行部０からｎ−１までのｎ個の部分実行部を含む。各部分実行部は処理Ｑ（ｉ）（ｉ＝０〜ｎ−１）を行う。集合Ｓはｎ個に分割され、部分集合０の処理は部分実行部０が行う。同様に、部分集合１の処理は部分実行部１が、…部分集合ｎ−１の処理は部分実行部ｎ−１が行う。
【００６１】
各処理Ｑ（ｉ）の冒頭には、図１１に示したようにＳＡ命令が設けてある。最初にｉ番目の部分実行部に到達したスレッドがＳＡ命令を実行すると、ＮＯＰ命令と同様な動作となるので、ｉ番目の部分実行部の処理Ｑ（ｉ）の実行を行う。２番目以降に、ｉ番目の部分実行部に到達したスレッドがＳＡ命令を実行すると、Ｊｕｍｐ命令と同様な動作となり、（ｉ＋１）番目の部分実行部の先頭にＪｕｍｐし、再びＳＡ命令が実行される。（ｉ＋１）番目の部分実行部に最初に到達したスレッドがＳＡ命令を実行したのであれば、ＳＡ命令はＮＯＰ命令と同様な操作となり、２番目以降に到達したスレッドがＳＡ命令を実行したのであれば、Ｊｕｍｐ命令と同様な動作となる。したがって、（ｉ＋１）番目の部分実行部についても、最初に到達したスレッドが、（ｉ＋１）番目の部分実行部の処理Ｑ（ｉ＋１）を実行することになる。
【００６２】
次に、コンパイラ装置１の動作について、以下のＣ言語のソースプログラムを例にして、再度、説明する。
【００６３】
ｉｎｔ  ｎｕｍ  ＝  １００００００００；
ｄｏｕｂｌｅ  ａ［Ｎ］；
ｔｈｒｅａｄ＿ｐａｒａ＿ｓｔａｒｔ
ｆｏｒ（ｉ＝０；ｉ＜ｎｕｍ；ｉ＋＋）
ａ［ｉ］  ＝  ａ［ｉ］  ＊  ２；
ｔｈｒｅａｄ＿ｐａｒａ＿ｅｎｄ
【００６４】
ここで、ｔｈｒｅａｄ＿ｐａｒａ＿ｓｔａｒｔとｔｈｒｅａｄ＿ｐａｒａ＿ｅｎｄは、スレッド並列処理の開始位置と終了位置とを示す。
【００６５】
このプログラムを３個のスレッドで並列処理する場合の並列処理プログラムを生成する。上述のソースプログラムは要素数がｎｕｍ＝１００，０００，０００個の配列を処理するから、集合Ｓの要素数｜Ｓ｜は、ｎｕｍである。ここで、分割数ｎを決定の際に使用する閾値Ａは２０，０００，０００であるとする。ｎｕｍ／３＞Ａが成立するため（図８のステップＳ４１でＹＥＳ）、ｎ＝３＊ｋ＝３＊３より、ｎ＝９となる（同ステップＳ４２）。
【００６６】
集合Ｓの要素数｜Ｓ｜をｎで除した余りは、１である。図９のステップＳ５２において、ｉ＝０のときＹＥＳ、ｉ＝１から８のときは、ＮＯと判定される。よって、繰り返し数は、図９のステップＳ５３及びＳ５４により、
ｉｔｅｒ［０］＝１１１１１１１２
ｉｔｅｒ［ｉ］＝１１１１１１１１  （ｉ＝１〜８）
となる。
【００６７】
各部分実行部の処理を行う部分集合の先頭要素番号ａｄｄ［ｉ］は、図９のステップＳ５７からステップＳ６３の処理により、
ａｄｄ［０］＝０
ａｄｄ［ｉ］＝１１１１１１１２＋１１１１１１１１＊（ｉ−１）  （ｉ＝１〜８）
となる。
【００６８】
以上の結果から、コンパイラ装置１は、部分実行部０から部分実行部８を生成する。図１３は部分実行部の内容を示す説明図である。図１３Ａが０番目の部分実行部を、図１３ｂが８番目の部分実行部を示している。８番目の部分実行部の後は、全てのスレッドが同期をとり、並列実行区間の演算を終えるようになっている。
【００６９】
実施の形態１においては、以下の様な効果を奏する。コンパイラ装置１が生成し、並列処理装置２で動作する並列処理プログラムは、処理データをスレッド数よりも多くの部分集合に分割しておき、データの各部分集合に対する処理を行う部分実行部を生成する。部分実行部の冒頭には、ＳＡ命令を設けることにより、各部分実行部に最初に到達したスレッドが、部分実行部の処理を実行し、それ以降に到達したスレッドは次の部分実行部にジャンプする。ジャンプ先の部分実行部の冒頭にもＳＡ命令が冒頭に設けられており、同様な動作を行う。それにより、各スレッドの同期処理を行わずとも、各スレッドは未処理の部分集合についての処理を行うことが可能となり、全体の処理時間を短縮することが可能となる。
【００７０】
実施の形態２
実施の形態２では、リダクション指示節を持つ並列処理プログラムを対象とする。リダクション指示節は、リダクション演算をおこなう部分を並列処理したい場合に用いる指示説である。リダクション演算は、複数のプロセスが持つデータを対象とした演算である。代表的なリダクション演算としては、例えば、データの総和を求める演算、最大値、最小値を求める演算等が知られている。
【００７１】
リダクション演算では、最終的に、複数のスレッドの結果をまとめて、共有メモリ領域に書き込む必要がある。各スレッドが共有メモリ領域に書き込む際には、プロセッサのロック機能を使用して書き込みを行う。スレッド数が大きいとき、書き込みの競合が起き、ロック動作によって、待ち時間が発生する。実施の形態２では、当該待ち時間がより短くなるように構造を持つ並列処理プログラムを生成する。
【００７２】
図１４は並列処理プログラムの生成手順を示すフローチャートである。コンパイラ装置１のＣＰＵ１１は、ソースプログラムに書かれたリダクション指示節を持つ並列処理部分を分割する場合の分割数ｎを設定する（ステップＳ８１）。ｎはスレッド数ｋよりも大きな値とする。ＣＰＵ１１は並列処理部分をｎ個に分割し、図１２と同様な部分実行部｛Ｑ（０），…，Ｑ（ｎ−１）｝を生成する（ステップＳ８２）。
【００７３】
ＣＰＵ１１は変数ｔを１に設定する（ステップＳ８３）。変数ｔは演算結果を格納するための部分実行部を何回生成したかを示す変数である。ＣＰＵ１１は分割数ｍを算出する（ステップＳ８４）。ｍはｎ＞ｍとなる自然数である。ｍは先行する部分実行部の個数などを用いて適宜設定する。
【００７４】
ＣＰＵ１１は分割数ｍが所定数より小さいか否かを判定する（ステップＳ８５）。ＣＰＵ１１は、分割数ｍが所定数より小さくはないと判定した場合（ステップＳ８５でＮＯ）、｛Ｑ（０），…，Ｑ（ｎ−１）｝の結果を格納するための部分実行部｛Ｑｔ（０），…，Ｑｔ（ｍ−１）｝（格納コード）を生成し、部分実行部｛Ｑ（０），…，Ｑ（ｎ−１）｝の後に配置する（ステップＳ８６）。ＣＰＵ１１はｔを１増加させる（ステップＳ８７）。ＣＰＵ１１は処理をステップＳ８４に戻す。
【００７５】
ＣＰＵ１１分割数ｍが所定数より小さいと判定した場合（ステップＳ８５でＹＥＳ）、部分実行部｛Ｑｔ（０），…，Ｑｔ（ｍ−１）｝の演算結果を、例えば、アトミック演算命令を用いる従来の方法などを用いて、リダクション指示節に沿って、共有領域メモリに対して格納する命令を配置する（ステップＳ８８）。ＣＰＵ１１は処理を終了する。
【００７６】
図１５は並列処理プログラムの構成の一例を示す説明図である。上述したように、処理Ｑ（０）を行う部分実行部０から、処理Ｑ（ｎ−１）を行う部分実行部ｎ−１までのｎ個の部分実行部が配置されている。その後に、結果格納のための処理Ｑ１（０）を行う部分実行部０（２回目）から、処理Ｑ１（ｍ−１）を行う部分実行部ｍ（２回目）が配されている。さらに、その後に、演算結果を共有領域メモリに対して格納する命令を含む処理Ｑ２（０）を行う部分実行部０（３回目）などが配置されている。並列実行区間の最後には、全スレッドの同期処理が配置されている。
【００７７】
図１５に記載されているＱ（０）、Ｑ（１）からＱ１（０）に向かう矢印 は、Ｑ（０）、Ｑ（１）に対するリダクション指示節を考慮した演算結果を、Ｑ１（０）からアクセスの可能な領域に格納することを意味している。Ｑ１（０）からＱ２（０）に向かう矢印も、同様な内容を示す。
【００７８】
図１５に示した構成の並列処理プログラムの動作について説明する。並列処理装置２のＣＰＵ２１は、ｋ個のスレッドで並列処理を行う。部分実行部｛Ｑ（０）、…，Ｑ（ｎ−）｝に対する実行は、実施の形態１での処理と同様である。また、ＣＰＵ２１により実現される各スレッドは、リダクション指示節の内容に沿った演算結果を対応する次の部分実行部｛Ｑ１（０），…，Ｑ１（ｍ−１）｝がアクセス可能な領域に格納する。すなわち、Ｑ（ｎ−１）の次の処理に到達したスレッドは、次の部分実行部｛Ｑ１（０），…，Ｑ１（ｍ−１）｝の先頭にあるＱ１（０）に対する処理を行う。同様に、処理の行われていない部分実行部に対して、各スレッドが次々に処理を行う。
【００７９】
図１６は、並列処理プログラムの構成の一例を示す説明図である。図１６に示すのは、並列処理プログラムの並列実行区間の後半に実行される部分実行部の配置例を示している。図１６の例では、部分実行部｛Ｑｔ-1（１），…，Ｑｔ-1（ｊ）｝が配置されている。当該部分実行部｛Ｑｔ-1（１），…，Ｑｔ-1（ｊ）｝では、リダクション指示節にしたがって、演算結果を共有領域のメモリに対して格納する命令を、スレッドが実行する。最後の部分実行部の出口アドレスまで到達したスレッドは、他の全てのスレッドが当該並列実行区間の処理を終えるまで待つ。最後まで処理を行っていたスレッドが最後の部分実行部の出口アドレスに到達したら、他のスレッドと同期を取り、当該並列実行区間の処理を完了する。
【００８０】
実施の形態２では以下の効果を奏する。演算結果を格納するための処理を行う部分実行部の数が所定数以下になるまでは、ＳＡ命令が配置された部分実行部を生成し実行するので、メモリロックによる待ち時間を短縮することが可能となる。
【００８１】
図１７はコンパイラ装置１の機能構成の一例を示す説明図である。コンパイラ装置１は、算出部１１ａ、分割部１１ｂ、生成部１１ｃ、出力部１１ｄを含む。ＣＰＵ１１が制御プログラム１Ｐを実行することにより、コンパイラ装置１は以下のように動作する。
【００８２】
算出部１１ａは処理すべきデータ集合の要素数から、スレッド数よりも大きい前記データ集合の分割数を算出する。分割部１１ｂは算出した分割数に、データ集合を分割する。生成部１１ｃは分割したデータ集合の処理を行う複数の実行部、及び各実行部に最初に到達したスレッドが行うようにしてある命令を、各実行部の先頭に配してあるオブジェクトコードを生成する。出力部１１ｄは生成したオブジェクトを出力する。
【００８３】
各実施例で記載されている技術的特徴（構成要件）はお互いに組合せ可能であり、組み合わせすることにより、新しい技術的特徴を形成することができる。
今回開示された実施の形態はすべての点で例示であって、制限的なものでは無いと考えられるべきである。本発明の範囲は、上記した意味では無く、特許請求の範囲によって示され、特許請求の範囲と均等の意味及び範囲内でのすべての変更が含まれることが意図される。
【００８４】
以上の実施の形態に関し、さらに以下の付記を開示する。
【００８５】
（付記１）
処理すべきデータ集合の要素数から、スレッド数よりも大きい前記データ集合の分割数を算出し、
算出した分割数に、前記データ集合を分割し、
分割したデータ集合それぞれの処理を行う複数の実行コードを含み、各実行コードの先頭に、該実行コードに最初に到達したスレッドが処理を行う命令を配してあるオブジェクトコードを生成する
コンパイラプログラム。
【００８６】
（付記２）
処理すべきデータ集合の要素数から算出した、スレッド数よりも大きい分割数で前記データ集合を分割した部分集合それぞれを処理する複数の実行コードを含み、各実行コードの先頭に、該実行コードに最初に到達したスレッドが処理を行う命令が配してあり、
前記スレッド数のスレッドで、前記複数の実行コードの処理を並列的にコンピュータに行わせる
コンピュータプログラム。
【００８７】
（付記３）
処理すべきデータ集合の要素数から、スレッド数よりも大きい前記データ集合の分割数を算出する算出部と、
算出した分割数に、前記データ集合を分割する分割部と、
分割したデータ集合の処理を行う複数の実行部、及び各実行部に最初に到達したスレッドが行う命令を、各実行部の先頭に配してあるオブジェクトコードを生成する生成部とを備える
コンパイラ装置。
【００８８】
（付記４）
前記分割したデータ集合の処理結果を格納する複数の第１格納コードを含み、各第１格納コードの先頭には、該第１格納コードに最初に到達したスレッドが処理を行う命令を配してあるオブジェクトコードを出力する
付記１に記載のコンパイラプログラム。
【００８９】
（付記５）
前記複数の第ｎ格納コード（ただし、ｎは１以上の自然数）の処理結果を格納する第ｎ＋１格納コードを複数含み、
各第ｎ＋１格納コードの先頭には、該第ｎ＋１格納コードに最初に到達したスレッドが処理を行う命令を配してあるオブジェクトコードの出力を、前記第ｎ格納コードの個数が所定値よりも小さくなるまで、再帰的に行う
付記４に記載のコンパイラプログラム。
【符号の説明】
【００９０】
１  コンパイラ装置
１１    ＣＰＵ
１１ａ  算出部
１１ｂ  分割部
１１ｃ  生成部
１１ｄ  出力部
１２    ＲＡＭ
１３    ＲＯＭ
１４    大容量記憶装置
１５    入力部
１６    出力部
１７    通信部
１８    読取り部
１ａ    可搬型記憶媒体
１ｂ    半導体メモリ
１Ｐ    制御プログラム
２  並列処理装置
２１    ＣＰＵ
２２    ＲＡＭ
２３    ＲＯＭ
２４    大容量記憶装置
２５    入力部
２６    出力部
２７    通信部
２８    読取り部
２ａ    可搬型記憶媒体
２ｂ    半導体メモリ
２Ｐ    制御プログラム
【図１】
0006443125.tif 000002
【図２】
0006443125.tif 000003
【図３】
0006443125.tif 000004
【図４】
0006443125.tif 000005
【図５】
0006443125.tif 000006
【図６】
0006443125.tif 000007
【図７】
0006443125.tif 000008
【図８】
0006443125.tif 000009
【図９】
0006443125.tif 000010
【図１０】
0006443125.tif 000011
【図１１】
0006443125.tif 000012
【図１２】
0006443125.tif 000013
【図１３】
0006443125.tif 000014
【図１４】
0006443125.tif 000015
【図１５】
0006443125.tif 000016
【図１６】
0006443125.tif 000017
【図１７】
0006443125.tif 000018