説明

スパースな正値対象行列の連立1次方程式の演算処理方法、装置、プログラム

【課題】スパースな正値対象行列の連立1次方程式の解を求める並列計算時にメモリアクセスが同じメモリ格納領域に集中しないようにする。
【解決手段】分岐ノード集合検出部101は、エリミネーションツリーをルートノードからサーチし、並列レベル毎の分岐ノード集合を検出する。メモリ割付チェイン生成部102は、同じ並列レベルのサブツリーと、サブツリーを構成せずかつレベルが近接し並列計算される可能性の高いノード群に、それぞれ異なるメモリ格納領域を割り付ける。タスクチェイン生成部103は、複数のスレッドがサブツリー単位で構成するノード群を選択して演算処理を実行し、サブツリーを構成しないノードをリーフ側から順次選択して演算処理を実行タスクチェインを生成する。LDL^T分解実行部104は、タスクチェインに基づいて複数のスレッドに各ノードの演算処理の実行時に、前述のノード毎に割り付けられたメモリ格納領域を使用する。

【発明の詳細な説明】
【技術分野】
【0001】
開示する技術は、シミュレーションや数理モデルから生じるスパースな正値対象行列の連立1次方程式の解を求めることにより数理モデルの分析を行う技術に関する。
【背景技術】
【0002】
最近のスカラー計算機は、CPUの性能は高速化されているが、メモリのアクセスが局所的に集中するときに処理性能が低下する傾向にある。特に、スパースな正値対象行列の連立1次方程式をコレスキー分解(LDL^T分解)を行いながら解く場合、データの参照更新が局所的なメモリ格納領域に集中することが多く、これが原因で並列効率をうまく引き出せないことがある。
【0003】
以下にその実例を示す。
今、図13に示されるようなスパースな正値対象行列Lを考える。対角要素にノード番号、●は非ゼロ要素、○はLDL^T(又はLL^T)分解で発生したフィルイン(fill-in)を表す。
【0004】
left-looking法に基づくLDL^T分解は、次のようにして求めることができる。
行列Lのi行目のiを除いた非ゼロ要素を持つノードの集合が算出される。これをrowstruct(i) とする。例えば、rowstruct(4)={1,2,3}, rowstruct(8)={5,7}である。
【0005】
rowstruct(i) は、エリミネーションツリー(elimination tree)のノードi をルートノードとするpuruned row subtree を構成し、それから算出することができる。実際、{4} + {1,2,3}、{8}+{5,7}はsubtree(サブツリー、部分木)になっている。なお、この処理の詳細については、下記非特許文献1に記載されている。
【0006】
ノードi のLの列ベクトルをliとして、LDL^T分解の対角行列の対角要素をdiiとする。また、LDL^T分解を行う行列をAとし、この下三角行列のi 番目の列ベクトルをaiとする。

li ← ai − Σdjj ×lij ×lj ・・・(1)
j ∈ rowstruct(i)

li ← li /dii ,ここで dii=lii ・・・(2)

上記(1)式及び(2)式で示される処理がi=1 からn まで繰り返されることにより、li が算出される。
【0007】
li の計算は、rowstruct(i)の要素のノードjでlj が計算できていれば、それらを使ってそのjに関する計算をliに対して行うことができる。つまり、li=aiと初期化され、その時点で計算が終わっているljを使ってliに対する更新の計算が実行される。
【0008】
liの格納に必要なメモリ格納領域の大きさも、エリミネーションツリーのpuruned row subtreeを用いて計算することができる。つまり、ノードiを含むpuruned row subtreeの数を数えることにより、上記メモリ格納領域の大きさを算出することができる。
【0009】
また、liの非ゼロ要素のインデクス(行番号)の集合は、ノードi及びrowstruct(i)のインデクスの和を求めることで計算することができる。これらの計算処理は、入力配列Aを解析して求めることができ、symbolic decompositionと呼ばれている。この詳細については、下記非特許文献1に記載されている。
【0010】
これらの情報から、各column(列)のliは、非ゼロ要素を圧縮してcompressed column storage(圧縮列格納方式)でメモリに格納することができる。
また、ノードiの更新で、エリミネーションツリーのdescendantとなるノードのインデクスでiよりも大きなものは、ノードiのインデクスの部分集合になることが、上記(1)式からわかる。
【0011】
このことから、各liの更新の計算を、圧縮した状態で一時域で計算してインデクスサーチしてliの対応位置に加えることで実行できる。
liの並列計算に関して、ノードiの更新をスレッドに割り付けて並列に、参照可能なljを使ってliを計算できる。ノードiの更新が終わればこれが参照可能となるため、このノードを待っていたスレッドの計算が可能になる。更新の終わったスレッドには、タスクチェイン(タスクキュー)にある次に更新されるべきノードの計算が新たに割り当てられる。参照可能なノードjに関しての更新が実行され、まだ計算が完了していないノードは後回しにして処理される。利用可能なノードの計算が終わり、計算に必要なノードjが残っていれば、ノードjの計算が終わるのが待たれる。このようににして、パイプライン方式で、LDL^T分解計算の並列化を実現することができる。
【0012】
ここで、エリミネーションツリーは、次式で示される親子関係から算出することができる。

parent(i)=min { j | lji ≠ 0 , j > i } ・・・(3)
: Lのi番目の列で最初にゼロでない行番号

例えば、図13に示される行例において、ノード1の親はノード2、ノード2の親はノード4、ノード3の親はノード4などである。実際のエリミネーションツリーは、LDL^T分解される配列Aの下三角({aij | i ≧ j , j=1,…,n})をサーチすることで算出することができる。この処理の詳細は、下記非特許文献1に記載されている。
【0013】
図14は、上記(3)式に基づいて図13の行列に対して算出されるエリミネーションツリーの例を示す図である。このエリミネーションツリーの例から、例えば以下のような並列計算のための知見を得ることができる。
【0014】
まず、ノード4とノード7の間では参照される共通のノードはないため、ノード4及びノード7は独立に計算することができる。
一般には、前述の(1)式から、{ i } + rowstruct(i) と { j } +rowstruct(j) が共通部分を持たない場合、各々に属するliの計算は、独立に実行することができる。エリミネーションツリーにおいては、共通部分のないsubtree同士は、独立に計算可能である。subtreeの各ノードのliの計算に必要なノードは、ノードiをルートとするpuruned subtree なので、subtree内に含まれている。従って、共通部分のないsubtree同士は、相互に依存関係がないことになるので、独立な計算が可能である。
【0015】
図13及び図14において、LDL^T分解の結果におけるフィルインを含めた非ゼロ要素の数や各列の非ゼロ要素のインデクス(行番号)は、前述したように、分解の前にsymbolic decompositionによって求めることができる。
【0016】
eliminationツリーが、depth firstに従って、ルートノード(図14ではノード21)からサーチされることにより、各ノードに対してポストオーダで番号付けがなされる。なお、depth firstやポストオーダの意味については、実施形態の説明において詳細に説明する。図13及び図14の例では、ポストオーダと元の番号は一致している。
【0017】
subtree{1,2,3,4}とsubtree{5,6,7}が、前述の(1)式及び(2)式に従って分解される。このときの依存関係から、ポストオーダ順に計算が実行される。つまり、ノード1→2→3→4、及びノード5→6→7の順に計算が実行される。これら2系列の計算は、並列に計算可能である。
【0018】
上記計算が終わったら、ノード8→9→...→21という順で計算が実行される。ノード8,9は、共に7の列を参照するため、列7を用いて更新する箇所は並列に計算でき、ノード7の計算が終わっていれば計算可能である。8,9,10と空いたスレッドが発生するたびに、タスクチェインからノードが割り当てられ列の更新が受け持たされる。ノード11〜ノード20までの計算も、上記の場合と同様の依存関係がある。例えば、列13が計算でき、ノード14,15を並列に更新できる。ノード14の更新が終われば、このスレッドにノード16が割り当てられる。そして、ノード15の更新と16の更新が並列に実施される。
【0019】
このようにして、パイプライン方式で更新を実行することができる。
本出願が開示する技術に関連する従来技術として、下記先行技術文献が開示されている。
【先行技術文献】
【非特許文献】
【0020】
【非特許文献1】T.DAVIS, Direct Methods for Sparse Linear Systems, SIAM 2006
【発明の概要】
【発明が解決しようとする課題】
【0021】
ここで、上述した従来の並列計算方式において、計算結果のメモリ格納領域としては、1からnまでのcolumn(列)の大きさ(column count)を加算した大きさのメモリ格納領域が割り当てられる。この場合に、compressed column storage方式で行列Lが格納されてゆく。liが、1からnまでつなげた領域に格納される。
【0022】
例えば、メモリが3個の部分に分かれていて、メモリ格納領域もほぼ3つ程度に均等にわたって存在するとする。そして、メモリ格納領域が単純に、各liのインデックスiの大きさに応じて3等分されるとする。そのとき、subtree{1,2,3,4}とsubtree{5,6,7}が並列に計算されると、図13より、1番目のメモリ格納領域(i=1〜7に対応)ばかりがアクセスされることになる。またその後、ポストオーダ順にノード11〜20までがパイプライン的に並列に処理される。このとき2番目(i=8〜14に対応)、3番目(i=15〜21に対応)のエリアばかりが局所的にアクセスされることになる。つまり、アクセスが局所的なメモリ格納領域に集中する。
【0023】
並列度が2から3に上げられるとき、図13及び図14の例では、並列に実行されるsubtreeは3個はない。このため、並列処理の粒度を下げてバランスをとるために、subtreeの計算を並列の対象からはずすことが望ましい。この場合、計算処理がポストオーダ順に実行され、パイプライン処理での並列性が引き出される。このとき、ポストオーダ順にタスクチェインが作成され、ノードのliの更新処理が、各スレッドにパイプライン処理として割り当てられる。しかし、このような方式が採用された場合、メモリに対するアクセスが局所的に集中していってしまうという問題点を有していた。
【0024】
つまり従来は、並列度を上げてゆけば、並列実行をパイプラインで行える範囲で理論的には性能が向上するはずである。しかし、メモリのアクセスの局所化が増すため、かえって計算効率が低下してしまう可能性が高いという問題点を有していた。
【0025】
開示する技術が解決しようとする課題は、並列計算時にメモリアクセスが同じメモリ格納領域に集中しないようにすることにある。
【課題を解決するための手段】
【0026】
上記課題を解決するために、開示する技術は、スパースな正値対象行列の連立1次方程式を解く演算処理を、該正値対象行列のコレスキー分解に先立ち入力行列の非零要素の構造を解析してえられるエリミネーションツリーを構成するスーパーノードを単位として実行する演算処理方法、装置、又はプログラムとして実現され、以下の構成を有する。
【0027】
分岐ノード集合検出処理ステップ又は分岐ノード集合検出処理部は、エリミネーションツリーをそのルートノードからサーチすることにより、並列レベル毎の分岐ノードの集合を検出する。
【0028】
サブツリーメモリ格納領域割付けステップ又はサブツリーメモリ格納領域割付け部は、分岐ノードの集合のうち、その集合の要素数が連続にメモリデータが割り当てられる記憶単位である複数のメモリ格納領域の数以上となる集合をサーチし、そのサーチで得られる分岐ノードの集合に含まれる各分岐ノードをルートノードとする各サブツリー毎に、そのサブツリーを構成するノード群に対する列ベクトルの演算結果を複数のメモリ格納領域から所定の選択規則によって選択したメモリ格納領域に割り付ける。
【0029】
ノードメモリ格納領域割付けステップ又はノードメモリ格納領域割付け部は、エリミネーションツリーを構成するノード群のうち、前述のサーチで得られる分岐ノードの集合に対応する各サブツリーを構成するノード群を含まないノード群に対する列ベクトルの演算結果を、並列レベルが近接しているノード群の演算結果はそれぞれ異なるメモリ格納領域に割り付けられるようにして、複数のメモリ格納領域から所定の選択規則によって選択したメモリ格納領域に割り付ける。
【0030】
上述の構成に加えて、以下の構成を有する。
サブツリーチェイン生成ステップ又はサブツリーチェイン生成部は、分岐ノードの集合のうち、その集合の要素数が並列実行される複数のスレッドの数以上となる集合をサーチし、そのサーチで得られる分岐ノードの集合に含まれる各分岐ノードをルートノードとする各サブツリーに関する情報をその各サブツリー単位で第1のタスクチェインであるサブツリーチェインに接続する。
【0031】
ノードチェイン生成ステップ又はノードチェイン生成部は、エリミネーションツリーを構成するノード群のうち、スレッドに関するサーチで得られる分岐ノードの集合に対応する各サブツリーを構成するノード群を含まないノード群を、エリミネーションツリーのリーフノードからルートノードに向かう順でかつ並列レベル毎にまとまるようにして、第2のタスクチェインであるノードチェインに接続する。
【0032】
そして、各スレッドは、サブツリーチェインに接続されている各サブツリーに関する情報を登録順に選択してその情報に対応するサブツリーを構成するノード群に対する列ベクトルの演算を実行し、サブツリーチェインで選択すべきエントリがなくなったら、ノードチェインに接続されている各ノードに対する列ベクトルの演算を登録順に実行する。
【発明の効果】
【0033】
開示する技術によれば、同じ並列レベルのサブツリーの並列計算時に各サブツリーを構成するノード同士が集中して同じメモリ格納領域にアクセスするという状況を回避することが可能となる。
【0034】
また開示する技術によれば、ノードの並列計算時にそれらのノード同士が集中して同じメモリ格納領域にアクセスするという状況を回避することが可能となる。
そして開示する技術によれば、各スレッドは概ね独立したメモリ格納領域をアクセスする。この結果、アクセスが集中することがないため、メモリアクセスのボトルネックが発生せず、並列度が上げたときに処理性能が著しく劣化することを回避することが可能となる。
【図面の簡単な説明】
【0035】
【図1】実施形態の構成図である。
【図2】分岐ノード集合検出処理を示す動作フローチャートである。
【図3】メモリ割付チェイン生成処理を示す動作フローチャートである。
【図4】タスクチェイン生成処理を示す動作フローチャートである。
【図5】LDL^T分解実行処理を示す動作フローチャートである。
【図6】エリミネーションツリーの例を示す図である。
【図7】実施形態のデータ構成図(その1)である。
【図8】実施形態のデータ構成図(その2)である。
【図9】実施形態の動作説明図である。
【図10】実施形態のデータ構成図(その3)である。
【図11】実施形態が適用されるハードウェアシステム構成の例を示す図(その1)である。
【図12】実施形態が適用されるハードウェアシステム構成の例を示す図(その2)である。
【図13】LDL^T分解処理を行う正値対象行例の例を示す図である。
【図14】図12の正値対象行列の例に対応するエリミネーションツリーを示す図である。
【発明を実施するための形態】
【0036】
以下、実施形態について詳細に説明する。
スパースな正値対象行列のLDL^T分解は、以下に示される方法で行われる。まず、スパース行列データが、compressed column storage(圧縮列格納方式)などの圧縮格納方式によってメモリに格納される。これにより、対角要素を含む下三角行列部分の非ゼロ要素が圧縮してメモリに格納される。列同士の依存関係や分解で新たに発生する非ゼロ要素が考慮されて、非ゼロパターンが同じか似ている列が並べ替えられて、1つのpanel(ブロック)にまとめられる。ブロックはスーパーノードと呼ばれ、複数のノードからなる。分解過程で生じるスーパーノード間のデータ依存関係が木構造で表現されて処理が実行される。この木のことをエリミネーションツリー(elimination tree)と呼ぶ。
【0037】
これらの木を構成するノードはスーパーノードであり、親子関係で表現できる。
ノードがleft-looking法で更新されてゆくとき、そのノードに関するpruned row subtreeの情報に基づいて、更新により参照されるrow structure(行構造)が決まる。pruned row subtreeは、エリミネーションツリーのsubtree(サブツリー、部分木)である。
【0038】
このため、エリミネーションツリーのリーフを持つsubtreeで、お互いに共通部分を持たないものは独立に分解の計算を行うことができる。この処理の詳細については、例えば前述の非特許文献1に詳細に記載されている。
【0039】
並列計算を行う上では、各々のsubtreeを構成するスーパーノードに対するブロックを格納するメモリ格納領域は、互いに近くに割り付けられるのがよい。
更に処理が進むと、木のルート(root)の方向に処理が進みながら、更新されるべきノードが順次選択されてゆく。処理がルートに近づくほど、一般に独立なsubtreeは減ってゆく。各ノードの依存関係が考慮されながらノードに対するブロックの更新が並列処理されてゆく。スパース行列のために、参照・更新されるノードは限られる。このため、単純に木の構造を構成するノードで近いものがメモリ上でも近くのメモリ格納領域に割り当てられると、メモリへの参照・更新が局所的な部分に集中してしまう。
【0040】
これを避けるために、並列処理の対象が、subtreeで分けられない部分と分けられる部分に分割される。そして、分解結果を格納する領域が複数の連続する部分に分割されることにより、subtreeを構成するノードに対応するブロック列ベクトルの格納領域が異なる部分連続領域に割り当てられるように制御が行われる。
【0041】
subtreeが取り除かれた部分の要素となるノードに関しては、木のルートからsubtreeのルート又は木のリーフに届くまで、同じ並列レベルのノードがまとめられながら、木が辿られてゆく。そして、辿られたルートと逆ルートが辿られながら、各ノードが異なる部分連続領域にサイクリックに割り付けられてゆく。
【0042】
並列処理に関しては、上述の割付けと同様の方式でタスクチェインが生成される。並列処理を実行するスレッド数を#Pとして、#P個以上のsubtreeがあれば、これらのsubtreeのルートとなるノードがタスクチェイン(subtree chain:サブツリーチェイン)に接続される。subtreeが取り除かれたノードに関しても部分連続領域の割付けと同様にして、木のルートからsubtreeのルート又は木のリーフに届くまで、同じ並列レベルのノードがまとめられながら、木が辿られてゆく。そして、辿られたルートと逆ルートを辿る順番のノードのチェインが生成され、ノードのタスクチェイン(node chain:ノードチェイン)とされる。
【0043】
以上の制御処理により、並列計算を行えるスレッド数が変わっても、同じメモリ格納領域へのメモリアクセスが集中することを避けることができる。
【0044】
エリミネーションツリーについて、以下に説明する。
本実施形態では、エリミネーションツリーは、全ノード数を#nodeとする1次元配列parentを用いて表現される。例えば、j=parent(i)は、「ノードiの親(parent)はノードjである」という意味を表現している。
【0045】
エリミネーションツリー上のノードの子及び兄弟の関係は、1次元配列child及びbrotherを用いて表現される。ノードj がノードi の子であれば、child(i)=jである。ノードi に子がなければ、child(i)=0である。
【0046】
子が複数存在する場合には、1つの子が親のchildとされ、その他の子はそのchildのbrotherとして表現される(親の子とはされない)。ノードj のbrotherとしてj1,j2があれば、brother(j)=j1, brother(j1)=j2, brother(j2)=0 と表現される。
【0047】
或るノードに対するfirstdescendant(ファーストディッセンダント:第1子孫)とは、そのノードから子(兄弟ではない)を辿って到達する、子がないノード即ちリーフノードのことをいう。例えば図6では、ノード7のfirstdescendantはノード1、ノード6のfirstdescendantはノード4などである。
【0048】
ここで、ポストオーダを、depth firstで、エリミネーションツリーがルートノード15からサーチされ、サーチ順に各ノードに番号が付与されるときの順番と定義する。図6においては、ポストオーダは、1,2,3,...,14となる。
【0049】
depth firstとは、以下のようなサーチ手順をいう。まず、ルートノードから子が辿られて、最も深いノード例えばノード1がサーチされる。1ノード分だけ親=ノード3に戻って、その親の子のうちノード1の兄弟例えばノード3が辿られる。再び、1ノード分だけ親=ノード3に戻って、その親の子にはノード1の兄弟はもうないため、更に親=ノード7に戻って、そこから子が辿られて、最も深いノード例えばノード4がサーチれる。以下同様にエリミネーションツリーがで辿られて、ポストオーダが決定される。このように、常に深いノードが優先されるサーチ手順をdepth firstと呼ぶ。
【0050】
subtreeは、ノード1〜7によって構成される部分集合や、ノード8〜14によって構成される部分集合などをいう。また、3つのノードからなるノード1〜3、ノード4〜6、ノード8〜10、ノード11〜12の各部分集合も、subtreeである。
【0051】
リーフとは、子を持たないノードをいう。図6では、1,2,4,5,6,9,11,12がリーフである。
上述のエリミネーションツリーを用いることにより、スパース行列で、ノードに対応する列ベクトルを束ねたスーパーノードが検出される。スーパーノードを構成するノードの非ゼロ要素の存在する行のみが圧縮され、2次元のpanel(パネル)に分解結果が格納される。
【0052】
各スーパーノードに対応するpanelの大きさは、分解結果の非ゼロパターンに対してsymbolic decompositionが実行されることにより決定され、実際の分解を行う前に知ることができる。
全panelを格納する1次元配列が用意され、この1次元配列のどの要素位置に各スーパーノードに対応するpanelが配置されるかが決定される。
【0053】
図1は、上述の基本的な考え方に基づく実施形態の構成図である。
この実施形態は、分岐ノード集合検出部101、メモリ割付チェイン生成部102、タスクチェイン生成部103、LDL^T分解実行部104を含む。
【0054】
分岐ノード集合検出部101
ステップ1.エリミネーションツリーデータ(parent配列、child配列、brother配列)が入力される。そして、それによって表現されるエリミネーションツリーにおいて、ルートノードからサーチが行われ、兄弟が複数ノードある、同じ並列レベルの分岐ノードの集合が、レベル毎に検出される。
【0055】
メモリ割付チェイン生成部102
ステップ2.ステップ1.で検出されたレベル毎の分岐ノードの集合のうち、集合の要素数が連続にメモリデータを割り当てるセクション(メモリ格納領域)の数以上となるものが、レベルが低いものから順にサーチされる。
【0056】
ステップ3.見つかった場合、この集合から分岐ノードが取り出され、このノードがルートノードとされるsubtreeがポストオーダー順に取り出され、各メモリ格納領域のための割付チェインに接続される。このとき、1つのsubtreeの構成ノードは、同じ割付チェインに接続される。subtree毎に、それが割り付けられるべきメモリ格納領域を指定する割付チェインが、サイクリックな順番で決められる。この結果、同じ並列レベルのsubtreeには、並列計算の実行時に、それぞれ異なる割付チェインを介して異なるメモリ格納領域が割り付けられることになる。即ち、同じ並列レベルのsubtreeの並列計算時に各subtreeを構成するノード同士が集中して同じメモリ格納領域にアクセスするという状況を回避することができる。
【0057】
ステップ4.ステップ3.で割付けが行われたsubtreeを除いたノードが、ルートノードから同じ並列レベルのノードが集まるようにしてリーフ方向にサーチされる。このサーチがステップ3.で割り付けられた分岐ノードかリーフノードに到達すれば、そのサーチは終了する。サーチされたノードは、サーチの順にstack(後述するwork配列)に積まれる。サーチが終わったら、stackが順にpopされながらサーチの逆順でノードが取り出され、その各ノードに対して、サイクリックな順番で割付チェインが決定される。この結果、レベルが近接し並列計算される可能性の高いノード群には、それぞれ異なる割付チェインを介して異なるメモリ格納領域がサイクリックに割り付けられることになる。これにより、ノードの並列計算時にそれらのノード同士が集中して同じメモリ格納領域にアクセスするという状況を回避することができる。
【0058】
タスクチェイン生成部103
ステップ5.ステップ1.で検出されたレベル毎の分岐ノードの集合のうち、集合の要素数が並列実行されるスレッドの数以上となる集合が、レベルの低いものから順にサーチされる。
【0059】
ステップ6.ステップ5.で検出された分岐ノードの集合に含まれる分岐ノードが順次、subtree chainに接続される。
【0060】
ステップ7.ステップ6.で処理された各分岐ノードがルートノードとされる各subtreeを除いたノードが、ルートノードから同じ並列レベルのノードが集まるようにしてリーフ方向にサーチされる。このサーチがステップ6.でsubtree chainに接続された分岐ノードかリーフに到達すれば、そのサーチは終了する。サーチされたノードは、サーチの順にstack(後述するwork配列)に積まれる。サーチが終わったら、stackが順にpopされながらサーチの逆順でノードが取り出され、その各ノードがnode chainに接続される。
【0061】
LDL^T分解実行部104
ステップ8.ステップ6.にて生成されたsubtree chainにエントリがあるうちは、subtree chainの先頭から順次各分岐ノードがスレッドの並列数ずつ取り出され、各スレッドに割り当てられる。各スレッドでは、割り当てられた分岐ノードに対応するsubtreeを構成する各ノードに対して、left-lookingなLDL^T分解が実行される。subtree chainのエントリがなくなったら、ステップ7.にて生成されたnode chainの先頭から順次各ノードがスレッドの並列数ずつ取り出され、各スレッドに割り当てられる。各スレッドでは、割り当てられたノードに対して、left-lookingなLDL^T分解が実行される。
【0062】
ここで、分岐ノード集合検出部101が実行するステップ1は、特許請求の範囲における分岐ノード集合検出処理ステップに対応する。メモリ割付チェイン生成部102が実行するステップ2.及び3.は、特許請求の範囲におけるサブツリーメモリ格納領域割付けステップ又はサブツリーメモリ格納領域割付け部に対応する。メモリ割付チェイン生成部102が実行するステップ4.は、特許請求の範囲におけるノードメモリ格納領域割付けステップ又はノードメモリ格納領域割付け部に対応する。タスクチェイン生成部103が実行するステップ5.及び6.は、特許請求の範囲におけるサブツリーチェイン生成ステップ又はサブツリーチェイン生成部に対応する。タスクチェイン生成部103が実行するステップ7.は、特許請求の範囲におけるノードチェイン生成ステップ又はノードチェイン生成部に対応する。
【0063】
以上の各部の処理を実現するための本実施形態の詳細な処理について、従来技術の説明において用いた図13に示される行列と図14に示されるエリミネーションツリーの例と、図2から図5の動作フローチャート、及びを用いて、以下に説明する。
【0064】
図2は、分岐ノード集合検出部101が実行する前述のステップ1.の分岐ノード集合検出処理の詳細を示す動作フローチャートである。
図7は、エリミネーションツリーのルートノードをレベル1として、レベル1から順次増加するレベル毎に、各レベルに属する分岐ノードの集合を管理するための配列データの構成例を示した図である。
【0065】
図7(b)は、分岐ノードを、エリミネーションツリーのルートノードからリーフノードに向かって検出された順に登録する1次元配列branchのデータ構成例である。ここで、branch配列の配列位置0(図7(b)の704)の配列要素値=21は、図14に示されるエリミネーションツリーのルートノードに対応し、レベル1の分岐ノードのノード番号を示している。配列位置1(図7(b)の705)の配列要素値=10は、図14に示されるエリミネーションツリーのノード10に対応し、レベル2の分岐ノードのノード番号を示している。配列位置2及び3(図7(b)の706及び707)の配列要素値=4及び7は、図14に示されるエリミネーションツリーのノード4及びノード7に対応し、レベル3の分岐ノード群の各ノード番号を示している。
【0066】
図7(a)は、先頭からレベル1、2、3、・・・の順に、branch配列上における各レベルの分岐ノード群が格納されている先頭の配列位置を配列要素値として格納する1次元配列branchlvlのデータ構成例である。ここで、branchlvl配列の配列位置0(図7(a)の701)の配列要素値=0は、図7(b)のbranch配列上のレベル1の分岐ノード群(図7(b)ではノード21の1つのみ)が格納されている先頭の配列位置を示している。配列位置1の配列要素値=1(図7(a)の702)は、図7(b)のbranch配列上のレベル2の分岐ノード群(図7(b)ではノード10の1つのみ)が格納されている先頭の配列位置を示している。配列位置2の配列要素値=2(図7(a)の703)は、図7(b)のbranch配列上のレベル3の分岐ノード群(図7(b)ではノード4及び7の2つ)が格納されている先頭の配列位置を示している。
【0067】
分岐ノード集合検出部101によって実行される図2の動作フローチャートは、図7(a)に例示されるbranchlvl配列及び図7(b)に例示されるbranch配列を生成する処理である。
【0068】
以下の説明において、図14等に示されるエリミネーションツリーの各ノードは、エリミネーションツリーデータとして入力される前述したparent配列から取得でき、1つのノードに対する子ノードは前述したchild配列から取得でき、兄弟ノードは前述したbrother配列から取得できるものとする。
【0069】
図2において、まず、levelstart、levelend、ptrnext、ptrsearch、levelの各変数が初期化される(ステップS201)。levelstartは、レベル毎にそのレベルに属する各分岐ノードの下に更に分岐ノードがあるか否かが探索される際に、そのレベルに属する分岐ノード群のbranch配列上での先頭の配列位置を示す。levelstartの初期値は、0(branch配列の先頭(図7(b)の704))にセットされる。levelendは、レベル毎にそのレベルに属する各分岐ノードの下に更に分岐ノードがあるか否かが探索される際に、そのレベルに属する分岐ノード群のbranch配列上での末尾の配列位置を示す。levelendの初期値も、0にセットされる。ptrnextは、branch配列上で分岐ノードが格納されている末尾の配列位置を示す。ptrnextの初期値も、0にセットされる。ptrsearchは、レベル毎にそのレベルに属する各分岐ノードの下に更に分岐ノードがあるか否かが探索される際に、現在探索が行われている分岐ノードの配列位置を示す。ptrnextは、levelstartからlevelendまでの間の値をとり、初期は0にセットされる。levelは、現在処理が行われているレベルを示す。levelの初期値は、1(=エリミネーションツリーのルートノードのレベル)にセットされる。
【0070】
次に、ステップS202で、図7(a)の701として示されるように、branchlvl配列の先頭の配列位置0に、branch配列の先頭の配列番号0が、レベル1(level=1)のインデックスとして格納される。
【0071】
次に、ステップS203で、ptrsearch≦levelendが成立するか否かが判定される。始めは、ptrsearch=0≦levelend=0となるので、この判定はYESとなる。この結果、ステップS204へ移行する。
【0072】
ステップS204では、branch配列内の配列位置=ptrsearchのノードに子(child)があるか否かが判定される。図14に示されるように、branch配列内の配列位置0のノード21にはノード10のchildがあるので、この判定はYESとなる。この結果、ステップS205へ移行する。
【0073】
ステップS205では、childstart変数にchildの値が設定される。childstart=10となる。ここで、childstart変数は、現在探索を行っている分岐ノードを示す。
続いて、ステップS206では、childのノードに、更にchildとそのbrotherがあるか否かが判定される。今、図14に示されるように、child=10には、更にchild=4と、そのbrother=9があるので、この判定はYESとなる。この結果、ステップS207へ移行する。
【0074】
ステップS207では、ptrnext変数の値が+1される。即ち、ptrnext=0+1=1とされる。
続いて、ステップS208では、branchlvl配列のlevel変数の値に対応する配列位置に、レベル(level+1)のインデックスとして、ptrnext変数の値が格納される。上記配列位置に既に値が格納されている場合には、この処理は実行されない。今、図7(a)の702として示されるように、branchlvl配列の配列位置1(level=1)に、レベル2(=level+1)のインデックスとして、ptrnext=1が格納される。
【0075】
続いて、ステップS209では、childのノード番号がbranch配列のptrnextの値に対応する配列位置に格納される。ここでは、図7(b)の705に示されるように、child=10がbranchの配列位置1に格納される。
【0076】
続いて、ステップS212では、childstart変数で示されるノードにbrotherがあるか否かが判定される。今、図14に示されるように、childstart=10にbrother=20があるので、この判定はYESとなる。この結果、ステップS213へ移行する。
【0077】
ステップS213では、childstart変数の値とchildの値がchildstart変数で示されるノードのbrotherのノード値で置き換えられる。今、childstart=20、child=20とされる。続いて、ステップS206へ移行する。
【0078】
図14に示されるように、child=20には、更にその子としてchild=19があるが、そのbrotherはないので、ステップS206の判定はNOとなる。この結果、ステップS210へ移行する。
【0079】
上述のようにchild=20には更にchild=19があるので、ステップS210の判定はYESとなる。この結果、ステップS211に移行する。
ステップS211では、childのchildでchildが置き換えられる。即ち、child=19となる。続いて、ステップS206に移行する。
【0080】
以下、ステップS206→S210→S211→S206の処理が繰り返されることにより、childのノードが、図14に示されるように、19→18→17→16→15→14→13→12→11という順で移行してゆく。
【0081】
child=11になってステップS206が実行されたときに、図14に示されるように、child=11の下にchildはないので、ステップS206の判定はNOとなる。この結果、ステップS210へ移行する。
【0082】
上述のようにchild=11の下にはchildはないので、ステップS210の判定はNOとなる。この結果、ステップS212に移行する。
図14に示されるように、childstart=20にはbrotherがないので、ステップS212の判定はNOとなる。この結果、ステップS214へ移行する。
【0083】
ステップS214では、ptrsearch変数の値が+1される。即ち、ptrsearch=0+1=1とされる。続いて、ステップS203に移行する。
図7(b)の704として示されるようにレベル1の分岐ノードは1つ(=ノード21)のみであり、ptrsearch=1>levelend=0となるので、ステップS203の判定はNOとなる。この結果、ステップS215へ移行する。
【0084】
ステップS215では、レベル2のための更新処理が実行される。即ち、レベル2の先頭配列位置levelstartが、レベル1の末尾配列位置levelendの次の(+1した)配列位置とされる。また、レベル2の末尾配列位置levelendは、branch配列の現在の末尾配列位置ptrnextとされる。そして、変数lenの値として、len=levelend-levelstart+1が計算される。また、現在のレベルを示す変数level値がインクリメントされる。
【0085】
ステップS216では、変数lenの値が0よりも大きいか否かが判定される。直前のレベルにて分岐ノード群が検出されていれば、ptrnext値がインクリメントされておりそれに従ってlevelend値もインクリメントされて変数lenの値は0より大きくなる。この結果、ステップS216の判定がYESとなって、ステップS203に移行し、直前のレベルにて検出された分岐ノード群に対して更に探索が続行される。直前のレベルにて分岐ノード群が検出されていなければステップS216の判定はNOとなって、全ての処理を終了する。
【0086】
今、ステップS215にて、levelstart=0+1=1、levelend=ptrnext=1、len=1-1+1=1、level=1+1=2となる。この結果、len=1>0となってステップS216の判定はYESとなる。続いて、ステップS203に移行する。
【0087】
ptrsearch=1≦levelend=1となるので、ステップS203の判定はYESとなる。この結果、ステップS204へ移行する。
branch内の配列位置=ptrsearch=1のノード10(図7(b)の705)には、図14に示されるように、child=4があるので、ステップS204の判定はYESとなる。この結果、ステップS205へ移行する。
【0088】
ステップS205では、childstart=4とされる。
続いて、図14に示されるように、child=4には、更にchild=2と、そのbrother=3があるので、ステップS206の判定はYESとなる。この結果、ステップS207へ移行する。
【0089】
ステップS207では、ptrnext=1+1=2とされる。
続いて、ステップS208では、図7(a)の703に示されるように、branchlvl配列の配列位置level=2に、レベル3(=level+1)のインデックスとして、branch配列の末尾の配列位置ptrnext=2が格納される。
【0090】
続いて、ステップS209では、child=4がbranch配列の末尾のp配列位置ptrnext=2に格納される。続いて、ステップS212へ移行する。
図14に示されるように、childstart=4にはbrother=9があるので、ステップS212の判定はYESとなる。この結果、ステップS213へ移行する。
【0091】
ステップS213では、childstart=9、child=9とされる。続いて、ステップS206へ移行する。
図14に示されるように、child=9には、child=8があるが、そのbrotherはないので、ステップS206の判定はNOとなる。この結果、ステップS210へ移行する。
【0092】
上述のようにchild=9にはchild=8があるので、ステップS210の判定はYESとなる。この結果、ステップS211に移行する。
ステップS211では、child=8となる。続いて、ステップS206に移行する。
【0093】
図14に示されるように、child=8には、child=7があるが、そのbrotherはないので、ステップS206の判定はNOとなる。この結果、ステップS210へ移行する。
上述のようにchild=8にはchild=7があるので、ステップS210の判定はYESとなる。この結果、ステップS211に移行する。
【0094】
ステップS211では、child=7となる。続いて、ステップS206に移行する。
図14に示されるように、child=7には、更にchild=5と、そのbrother=6があるので、ステップS206の判定はYESとなる。この結果、ステップS207へ移行する。
【0095】
ステップS207では、branch配列の末尾の配列位置がptrnext=2+1=3とされる。
続いて、branchlvl配列の配列位置2(=level)に、レベル3(=level+1)のインデックス=2が既にあるから、ステップS208の処理は実行されない。
【0096】
続いて、ステップS209では、child=7がbranch配列の末尾の配列位置ptrnext=3に格納される。続いて、ステップS212へ移行する。
図14に示されるように、childstart=9にはbrotherがないので、ステップS212の判定はNOとなる。この結果、ステップS214へ移行する。
【0097】
ステップS214では、ptrsearch=1+1=2とされる。続いて、ステップS203に移行する。
図7(b)の705として示されるようにレベル2の分岐ノードは1つ(=ノード10)のみであり、ptrsearch=2>levelend=1となるので、ステップS203の判定はNOとなる。この結果、ステップS215へ移行する。
【0098】
今、ステップS215にて、levelstart=1+1=2、levelend=ptrnext=3、len=3-2+1=2、level=2+1=3となる。この結果、len=2>0となってステップS216の判定はYESとなる。続いて、ステップS203に移行する。
【0099】
ptrsearch=2≦levelend=3となるので、ステップS203の判定はYESとなる。この結果、ステップS204へ移行する。
図14に示されるように、branch配列内の配列位置ptrsearch=2のノード4にはchild=2があるので、ステップS204の判定はYESとなる。この結果、ステップS205へ移行する。
【0100】
ステップS205では、childstart=2とされる。
図14に示されるように、child=2には、child=1があるが、そのbrotherはないので、ステップS206の判定はNOとなる。この結果、ステップS210へ移行する。
【0101】
上述のように、child=2にはchild=1があるので、ステップS210の判定はYESとなる。この結果、ステップS211に移行する。
ステップS211では、child=1となる。続いて、ステップS206に移行する。
【0102】
図14に示されるように、child=1はリーフノードであってchildはないので、ステップS206の判定はNOとなる。この結果、ステップS210へ移行する。
上述のようにchild=1にはchildはないので、ステップS210の判定はNOとなる。この結果、ステップS212に移行する。
【0103】
図14に示されるように、childstart=2にbrother=3があるので、ステップS212の判定はYESとなる。この結果、ステップS213へ移行する。
ステップS213では、childstart=3、child=3とされる。続いて、ステップS206へ移行する。
【0104】
図14に示されるように、child=3はリーフノードであってchildはないので、ステップS206の判定はNOとなる。この結果、ステップS212に移行する。
図14に示されるように、childstart=3にはbrotherがないので、ステップS212の判定はNOとなる。この結果、ステップS214へ移行する。
【0105】
ステップS214では、ptrsearch=2+1=3とされる。続いて、ステップS203に移行する。
図7(b)の706及び707として示されるようにレベル3の分岐ノードは2つ(=ノード4及び7)であり、現在ノード4の処理が終わってノード7の処理に移っており、ptrsearch=3≦levelend=3となるので、ステップS203の判定はYESとなる。この結果、ステップS204へ移行する。
【0106】
branch内の配列位置ptrsearch=3のノード7には、図14に示されるように、child=5があるので、ステップS204の判定はYESとなる。この結果、ステップS205へ移行する。
【0107】
ステップS205では、childstart=5とされる。
続いて、図14に示されるように、child=5はリーフノードでありchildはないので、ステップS206の判定はNOとなる。この結果、ステップS212に移行する。
【0108】
図14に示されるように、childstart=5にbrother=6があるので、ステップS212の判定はYESとなる。この結果、ステップS213へ移行する。
ステップS213では、childstart=6、child=6とされる。続いて、ステップS206へ移行する。
【0109】
図14に示されるように、child=6はリーフノードでありchildはないので、ステップS206の判定はNOとなる。この結果、ステップS212に移行する。
図14に示されるように、childstart=6にはbrotherがないので、ステップS212の判定はNOとなる。この結果、ステップS214へ移行する。
【0110】
ステップS214では、ptrsearch=3+1=4とされる。続いて、ステップS203に移行する。
図7(b)の706及び707として示されるようにレベル3の分岐ノードは2つ(=ノード4及び7)であり、ノード4とノード7の処理が共に終了しており、ptrsearch=4>levelend=3となるので、ステップS203の判定はNOとなる。この結果、ステップS215へ移行する。
【0111】
ステップS215では、levelstart=3+1=4、levelend=ptrnext=3、len=3-4+1=0、level=3+1=4となる。この結果、len=0=0となってステップS216の判定はNOとなって、全ての処理を終了する。
【0112】
以上のようにして、エリミネーションツリーが解析され、図7(a)に例示されるbranchlvl配列及び図7(b)に例示されるbranch配列が生成される。
次に、図3は、図1のメモリ割付チェイン生成部102が実行する前述のステップ2.から4.のメモリ割付チェイン生成処理の詳細を示す動作フローチャートである。ここでは、エリミネーションツリー上の各ノードに対して、メモリ格納領域が割付けられる。
【0113】
まず、例として、並列計算の処理結果を保存する領域が、2つのメモリ格納領域に分割されていると仮定する。今、例えば2つのメモリ格納領域に図14に示されるようなエリミネーションツリーを構成するノードが割り付けられる場合、例えば図8に示されるようなデータ構成を採用することができる。
【0114】
まず、図8(a)に例示されるように、エリミネーションツリーを構成する各ノードに配列位置が一意に対応する1次元ノード配列800が用意される。例えば、配列位置0は図14のノード21に対応し、配列位置1は図14のノード10に対応し、配列位置2は図14のノード4に対応するといった如くである。そして、メモリ格納領域1において実行されるノード群はその実行順に、割付チェインchain1に割り付けられる。この場合まず、図8(a)に示されるように、割付チェインchain1の先頭を示すレジスタ801が用意され、このレジスタ801に、メモリ格納領域1にて実行される最初のノードに対応する1次元ノード配列800上の配列位置が格納される。次に、このレジスタ801から参照される1次元ノード配列800上の配列位置には、2番目に実行されるノードに対応する1次元ノード配列800の配列位置が格納される。以下同様にして、1次元ノード配列800上の各配列位置に、その配列位置に対応するノードの次に実行されるノードに対応する配列位置が格納されてゆく。最後に実行されるノードの配列位置には、nullデータが格納される。このようにして、割付チェインchain1として、レジスタ801から順次1次元ノード配列800上の配列位置が辿られることにより、メモリ格納領域1において実行されるノードとその実行順を設定することができる。割付チェインchain1の場合と同様にして、メモリ格納領域2において実行されるノード群もその実行順に、割付チェインchain2に割り付けられる。この場合まず、図8(a)に示されるように、割付チェインchain2の先頭を示すレジスタ802が用意され、このレジスタ802に、メモリ格納領域2にて実行される最初のノードに対応する1次元ノード配列800の配列位置が格納される。次に、このレジスタ802から参照される1次元ノード配列800上の配列位置には、2番目に実行されるノードに対応する1次元ノード配列800の配列位置が格納される。以下同様にして、1次元ノード配列800上の各配列位置に、その配列位置に対応するノードの次に実行されるノードに対応する配列位置が格納されてゆく。最後に実行されるノードの配列位置には、nullデータが格納される。
【0115】
以下の説明において、連続にメモリデータを割り当てるセクション(メモリ格納領域)のことをpool(プール)と呼び、その数を#poolと表記する。即ち、ここの仮定では、#pool=2である。
【0116】
図3の動作フローチャートにおいて、まず、図7(a)に示されるbranchlvl配列と図7(b)に示されるbranch配列がアクセスされることにより、#pool以上の要素数を有する分岐ノード集合が見つけられる(ステップS301)。ここで、branchlvl配列とbranch配列は、図2の動作フローチャートで示される分岐ノード集合検出処理によって得られている。図7に示される配列構造の例から、レベル1(level 1)の分岐ノード集合は{21}(ノード21を要素とする集合)となる。次に、レベル2(level 2)の分岐ノード集合は{10}(ノード10を要素とする集合)となる。更に、レベル3(level 3)の分岐ノード集合は{4,7}(ノード4とノード7の集合)となる。そして、#pool=2とすると、2以上の要素数を有する分岐ノード集合は、level 3の分岐ノード集合{4,7}である。この結果、ステップS302の判定がYESとなる。
【0117】
以上のステップS301とS302の処理により、メモリ割付チェイン生成部102による前述のステップ2.の処理が実現される。
次に、ステップS301で見つかったlevel集合から、1つのノード=分岐ノードが取り出され、nodelvlとされる(ステップS303)。ここでは例えば、level 3の集合{4,7}からノード4がnodelvlとして取り出される。
【0118】
次に、図8(b)に例示されるような分岐ノード指示用1次元配列nmarkが用意される。図8(b)の1次元配列nmarkは、配列要素数が図8(a)の1次元ノード配列800と同じであり、図8(a)と同じ配列位置は同じノードに対応している。そして、各配列位置のノードが分岐ノードである場合には、その分岐ノードに対応する分岐ノード指示用1次元配列nmark上の配列位置にon(オン)を示す値が設定される。ここで、分岐ノード指示用1次元配列nmarkにおいて、ステップS303にて取り出されたノードnodelvl=4に対応する配列位置の配列要素が、onを示す値に設定される(ステップS304)。なお、nmark配列の各配列要素は、初期状態において全てクリアされている。
【0119】
次に、ノードnodelvlに対応するfirstdescendantのノードがfstdecs変数に設定される(ステップS305)。図14の例では、ノード4に対するfirstdescendantのノードはノード1であり、fstdecs=1である。
【0120】
続いて、現在選択されているpoolの割付チェイン(chain1又はchain2)に、fstdecsノードからnodelvlノードまでポストオーダで、順番に現在のsubtreeの構成要素ノードが接続される(ステップS306)。今例えば、pool1が選択されており、割付チェイン=chain1とする。そして、fstdecs=1からnodelvl=4までのポストオーダは、図14に示されるように、ノード1→ノード2→ノード3→ノード4である。従って、割付チェインchain1は、次のようになる。

chain1={1→2→3→4} ・・・(4)

この割付チェインchain1が、例えば図8(a)に示されるデータ構造を使って形成される。
【0121】
次に、現在選択されているpoolが、次式によりサイクリックに変更される(ステップS307)。なお、poolは、現在選択されているpool番号を示す変数である。また、mod(A,B)は、AをBで割った剰余を求める演算を示す。

pool=mod(pool,#pool)+1 ・・・(5)

今、#pool=2であり、現在のpool番号pool=1とすれば、上記計算の結果、新たなpool番号はpool=2となる。なお逆に、現在のpool番号pool=2とすれば、上記計算の結果、新たなpool番号はpool=1となる。
ここで、現在のpoolが1から2に変化した後、ステップS301で見つかったlevel集合に残りがあるか否かが判定される(ステップS308)。
【0122】
前述のlevel 3の集合{4,7}の場合、まだノード7が残っている。従って、ステップS308の判定がYESとなり、ステップS303の処理に戻る。この結果、level 3の集合{4,7}からノード7が取り出される(ステップS303)。次に、1次元配列nmark上の上記ノードnodelvl=7に対応する配列位置の配列要素が、onを示す値に設定される(ステップS304)。更に、nodelvlノード=4に対するfirstdescendantのノードとして、fstdecs=5が設定される(ステップS305)(図14参照)。続いて、現在選択されているpool=2の割付チェイン=chain2に、fstdecs=5からnodelvl=7までポストオーダで、順番に現在のsubtreeの構成要素ノードノード5→ノード6→ノード7が接続される(ステップS306)。従って、割付チェインchain2は、次のようになる。

chain2={5→6→7} ・・・(6)

以上のステップS303からS308の処理により、メモリ割付チェイン生成部102による前述のステップ3.の処理が実現される。
【0123】
次に、分岐ノード指示用1次元配列nmarkの配列要素がonとなっている分岐ノード又はリーフノードの何れかに辿り着くまで、エリミネーションツリーのルートノードから順に各ノードが辿られる。ここでは、図8(c)に示される1次元のwork配列が用意され、ルートから同じ並列レベルのノードが辿られ、辿られたノードがwork配列に順次格納されてゆく。この処理は、図3のステップS309からS313までの処理によって実現される。これらの処理について、図9の動作説明図を用いながら説明する。
【0124】
まず、ステップS309で、ルートノードが、分岐ノード指示用1次元配列nmark上でonされていなければwork配列に格納される。格納されればnodeend=1、格納されなければnodeend=0とされる。通常は、ルートノードはnmark上でonされていないため、nodeend=1となる(図9の行1)。nodeend=0となる場合は特殊な場合である。nodeendは、work配列の末尾の格納位置を示す。nodestartは、対象ノードのサーチ位置を示す。
【0125】
次に、ステップS310で、nodestart=1とされる(図9の行2)。なお、work配列の先頭の配列位置は1とする。
次に、ステップS311では、nodestart≦nodeendが成立するか否かが判定される。図9の行3の状態では、ステップS311の判定がYESとなり、ステップS312に移行する。
【0126】
ステップS312では、nodestartで示されるノードがwork配列から取り出され、そのノード(以下「対象ノード」と呼ぶ)のchild,brotherのノードが調べられる。そして、調べられたノードがnmark配列上でonされていないなら、nodeend=nodeend+1とされて、nodeendで示されるwork配列上の配列位置に、その調べられたノードが格納される。図9の行4の状態では、nodestart=1で示される配列位置のノード21がwork配列から取り出され、そのノード21のchild,brotherのノードが調べられる。ノード21は、図9の行1でwork配列の配列位置1にセットされている。図14の例では、ノード21のchildノードであるノード10、そのbrotherノードであるノード20の各ノードが調べられる。まず、ノード10は、前述のステップS301からS308の処理におけるメモリ割付対象とはなっておらず、nmark配列上でonされてはいない。このため、nodeend=1+1=2で示されるwork配列上の配列位置2に、ノード10が格納される(図9の行4)。続いて、ノード20も、前述のステップS301からS308の処理におけるメモリ割付対象とはなっておらず、nmark配列上でonされてはいない。このため、nodeend=2+1=3で示されるwork配列上の配列位置3に、ノード20が格納される(図9の行5)。
【0127】
対象ノードの全てのchild,brotherのノードのサーチが終了すると、ステップS313にて、nodestart=nodestart+1とされる。図9の行6の状態では、nodestart=1+1=2とされる。続いて、ステップS311に移行する。
【0128】
図9の行7の状態では、nodestart=2≦nodeend=3でステップS311の判定がYESとなり、ステップS312に移行する。
ステップS312において、図9の行8の状態では、nodestart=2で示される配列位置の対象ノード10がwork配列から取り出され、その対象ノード10のchild,brotherのノードが調べられる。対象ノード10は、図9の行4でwork配列の配列位置2にセットされている。図14の例では、対象ノード10のchildノードであるノード4、そのbrotherノードであるノード9の各ノードが調べられる。まず、ノード4は、前述のステップS301からS308の処理におけるメモリ割付対象となっており、nmark配列上でonされている。このため、ノード4はwork配列には格納されない。続いて、ノード9は、前述のステップS301からS308の処理におけるメモリ割付対象とはなっておらず、nmark配列上でonされてはいない。このため、nodeend=3+1=4で示されるwork配列上の配列位置4に、ノード9が格納される(図9の行8)。
【0129】
図9の行9の状態では、ステップS313において、nodestart=2+1=3とされる。続いて、ステップS311に移行する。
図9の行10の状態では、nodestart=3≦nodeend=4でステップS311の判定がYESとなり、ステップS312に移行する。
【0130】
ステップS312において、図9の行11の状態では、nodestart=3で示される配列位置の対象ノード20がwork配列から取り出され、その対象ノード20のchild,brotherのノードが調べられる。対象ノード20は、図9の行5でwork配列の配列位置3にセットされている。図14の例では、対象ノード20のchildノードであるノード19が調べられる。即ち、ノード19は、前述のステップS301からS308の処理におけるメモリ割付対象とはなっておらず、nmark配列上でonされていない。このため、nodeend=4+1=5で示されるwork配列上の配列位置5に、ノード19が格納される(図9の行11)。
【0131】
図9の行12の状態では、ステップS313において、nodestart=3+1=4とされる。続いて、ステップS311に移行する。
図9の行13の状態では、nodestart=4≦nodeend=5でステップS311の判定がYESとなり、ステップS312に移行する。
【0132】
ステップS312において、図9の行14の状態では、nodestart=4で示される配列位置の対象ノード9がwork配列から取り出され、その対象ノード9のchild,brotherのノードが調べられる。対象ノード9は、図9の行8でwork配列の配列位置4にセットされている。図14の例では、対象ノード9のchildノードであるノード8が調べられる。即ち、ノード8は、前述のステップS301からS308の処理におけるメモリ割付対象とはなっておらず、nmark配列上でonされていない。このため、nodeend=5+1=6で示されるwork配列上の配列位置6に、ノード8が格納される(図9の行14)。
【0133】
図9の行15の状態では、ステップS313において、nodestart=4+1=5とされる。続いて、ステップS311に移行する。
図9の行16の状態では、nodestart=5≦nodeend=6でステップS311の判定がYESとなり、ステップS312に移行する。
【0134】
ステップS312において、図9の行17の状態では、nodestart=5で示される配列位置の対象ノード19がwork配列から取り出され、その対象ノード19のchild,brotherのノードが調べられる。対象ノード19は、図9の行11でwork配列の配列位置5にセットされている。図14の例では、対象ノード19のchildノードであるノード18が調べられる。即ち、ノード18は、前述のステップS301からS308の処理におけるメモリ割付対象とはなっておらず、nmark配列上でonされていない。このため、nodeend=6+1=7で示されるwork配列上の配列位置7に、ノード18が格納される(図9の行17)。
【0135】
図9の行18の状態では、ステップS313において、nodestart=5+1=6とされる。続いて、ステップS311に移行する。
図9の行19の状態では、nodestart=6≦nodeend=7でステップS311の判定がYESとなり、ステップS312に移行する。
【0136】
ステップS312において、図9の行20の状態では、nodestart=6で示される配列位置の対象ノード8がwork配列から取り出され、その対象ノード8のchild,brotherのノードが調べられる。対象ノード8は、図9の行14でwork配列の配列位置6にセットされている。図14の例では、対象ノード8のchildノードであるノード7が調べられる。即ち、ノード7は、前述のステップS301からS308の処理におけるメモリ割付対象とはなっており、nmark配列上でonされている。このため、ノード7はwork配列には格納されない(図9の行20)。
【0137】
図9の行21の状態では、ステップS313において、nodestart=6+1=7とされる。続いて、ステップS311に移行する。
図9の行22の状態では、nodestart=7=nodeend=7でステップS311の判定がYESとなり、ステップS312に移行する。
【0138】
ステップS312において、図9の行23の状態では、nodestart=7で示される配列位置の対象ノード18がwork配列から取り出され、その対象ノード18のchild,brotherのノードが調べられる。対象ノード18は、図9の行17でwork配列の配列位置7にセットされている。図14の例では、対象ノード18のchildノードであるノード17が調べられる。即ち、ノード17は、前述のステップS301からS308の処理におけるメモリ割付対象とはなっておらず、nmark配列上でonされていない。このため、nodeend=7+1=8で示されるwork配列上の配列位置8に、ノード17が格納される(図9の行23)。
【0139】
以下同様の処理が実行され、work配列上の配列位置9〜14に、ノード16〜ノード11が順次格納される(図9の行24〜行41)。
図9の行42の状態では、ステップS313において、nodestart=13+1=14とされる。続いて、ステップS311に移行する。
【0140】
図9の行43の状態では、nodestart=14=nodeend=14でステップS311の判定がYESとなり、ステップS312に移行する。
ステップS312において、図9の行44の状態では、nodestart=14で示される配列位置の対象ノード11がwork配列から取り出されるが、図14に示されるように、対象ノード11にはchild,brotherのノードがない。このため、work配列へのノード格納は行われない(図9の行44)。なお、対象ノード11は、図9の行41でwork配列の配列位置14にセットされている。
【0141】
図9の行45の状態では、ステップS313において、nodestart=14+1=15とされる。続いて、ステップS311に移行する。
図9の行46の状態では、nodestart=15=nodeend=14でステップS311の判定がNOとなり、ステップS311の判定がNOとなって、ステップS314に移行する。
【0142】
以上説明した図3のステップS309からS313までの処理によって、nmark配列でonとなっている分岐ノード又はリーフノードの何れかに辿り着くまで、エリミネーションツリーのルートノードから順に各ノードを辿った結果が、work配列に得られる。図14に対応する図8の例では、work配列に得られた結果は次のようになる。

work={21|10,20|9,19|8,18|17|16|15|14|13|12|11} ・・・(7)

ここで、区切り記号「|」は、レベルの境界を示している。
【0143】
以上のようにしてwork配列が確定したら、ステップS314にて、n=nodeendから1まで1ずつ減じられながら辿られた順の逆順で各work配列要素work(n)のノードが順次取り出される。そして、work配列から順次取り出されたノードが、前述の(4)式及び(6)式として得られている割付チェインchain1及びchain2の末尾に、交互にサイクリックに追加されてゆく。この結果、割付チェインchain1及びchain2は、次のようになる。

chain1={1→2→3→4→11→13→15→17→8→9→10} ・・・(8)

chain2={5→6→7→12→14→16→18→19→20→21} ・・・(9)

【0144】
以上の処理により、ノードのメモリ割付け及び処理順が確定する。最後に、ステップS315にて、プール毎の割付チェインchain1又はchain2がプール番号順に取り出され、各割付チェインが辿られてノードが取り出され、各ノードに対して順番にメモリ格納領域が割り付けられる。
【0145】
前述したように、スパースな正値対象行列Lにおけるノードi の列ベクトルliの大きささは、symbolic decompositionと呼ばれる解析で求めることができる。各ノードに対するLDL^T分解計算結果は、各ノードが登録されている割付チェインに対応するメモリ格納領域に格納されることになる。即ち、chain1に接続される各ノードの処理結果が、この割付チェインでの各ノードの接続順で、メモリ格納領域の前半部分に割り当てられて格納される。同様に、chain2に接続される各ノードの処理結果が、この割付チェインでの各ノードの接続順で、メモリ格納領域の後半部分に割り当てられて格納される。
【0146】
今、上述の割付チェインchain1及びchain2に基づく各メモリ格納領域へのノード割当ての順番の対応表は、例えば図10(a)に示されるデータ構成例を有するアサインテーブル(assign table)に保持される。
【0147】
また、compressed column storage(圧縮列格納方式)の場合と同様に、相対的な割付順番がmであるノードに対応するpanel(columnを格納する領域)の先頭がメモリ格納領域のどの位置に存在するかが計算されて、その先頭位置を示す値が例えば図10(b)に示される1次元配列に格納される。
【0148】
また実際には、ノードに対するLDL^T分解結果は、非ゼロ要素を含む行のみが圧縮されて2次元配列のpanelに格納される。このため、panel毎にその1次元目の大きささと2次元目の大きさを対で記憶する例えば図10(c)に示される1次元配列も用意される。
【0149】
更には、非ゼロ要素を含む行を指示するためのインデクスの先頭位置を示す値が格納される例えば図10(d)に示される1次元配列も用意される(図10(e)参照)。
ステップS315では、図10に示されるようなメモリ割当て制御用のデータ群に対して、割付チェインchain1及びchain2に基づいてデータ設定が行われる。後述するLDL^T分解処理の実行時には、これらのデータ群が随時参照されて各ノードの計算結果をメモリ格納領域に割り当てるための制御が実行されることになる。
【0150】
次に、図4は、図1のタスクチェイン生成部103が実行する前述のステップ5.から7.の動作の詳細を示す動作フローチャートである。ここでは、エリミネーションツリー上の各ノードが、スレッドでの並列計算を制御するためのタスクチェインに登録される。
【0151】
タスクチェインは、subtree chainとnode chainを含む。タスクチェインのデータ構造の例としては、メモリ割付チェイン生成処理における割付チェインの場合と同様に、図8(a)に示されるようなデータ構造を採用することができる。また、以下の処理において使用される分岐ノード指示用1次元配列nmarkとwork配列のデータ構造例としても、メモリ割付チェイン生成処理の場合と同様の、図8(b)と(c)に示されるようなデータ構造を採用することができる。
【0152】
以下の説明では、並列実行されるスレッド数が2である場合の例について説明する。ここで、スレッド数を#threadと表現する。
図4の動作フローチャートにおいて、まず、図7(a)に示されるbranchlvl配列と図7(b)に示されるbranch配列がアクセスされることにより、#thread以上の要素数を有する分岐ノード集合が見つけられる(ステップS401)。ここで、branchlvl配列とbranch配列は、図2の動作フローチャートで示される分岐ノード集合検出処理によって得られている。図7に示される配列構造の例から、レベル1(level 1)の分岐ノード集合は{21}(ノード21を要素とする集合)となる。次に、レベル2(level 2)の分岐ノード集合は{10}(ノード10を要素とする集合)となる。更に、レベル3(level 3)の分岐ノード集合は{4,7}(ノード4とノード7の集合)となる。そして、#thread=2とすると、2以上の要素数を有する分岐ノード集合は、level 3の分岐ノード集合{4,7}である。この結果、ステップS402の判定がYESとなる。
【0153】
以上のステップS401とS402の処理により、タスクチェイン生成部103による前述のステップ5.の処理が実現される。
【0154】
次に、ステップS401で見つかったlevel集合から、1つのノード=分岐ノードが取り出され、nodelvlとされる(ステップS403)。ここでは例えば、level 3の集合{4,7}からノード4がnodelvlとして取り出される。
【0155】
次に、図8(b)に例示されるような分岐ノード指示用1次元配列nmarkが用意される。図8(b)の1次元配列nmarkは、配列要素数が図8(a)の1次元ノード配列800と同じであり、図8(a)と同じ配列位置は同じノードに対応している。そして、各配列位置のノードが分岐ノードである場合には、その分岐ノードに対応する分岐ノード指示用1次元配列nmark上の配列位置にon(オン)を示す値が設定される。ここで、分岐ノード指示用1次元配列nmarkにおいて、ステップS403にて取り出されたノードnodelvl=4に対応する配列位置の配列要素が、onを示す値に設定される(ステップS404)。なお、nmark配列の各配列要素は、初期状態において全てクリアされている。
【0156】
次に、ノードnodelvlに対応するfirstdescendantのノードがfstdecs変数に設定される(ステップS405)。図14の例では、ノード4に対するfirstdescendantのノードはノード1であり、fstdecs=1である。
【0157】
続いて、subtree chainと呼ばれる第1のタスクチェインに、ノードnodelvlが加えられる(ステップS406)。即ち、subtree chainは、次のようになる。

subtree chain={4} ・・・(10)

このsubtree chainが、例えば図8(a)に示されるデータ構造を使って形成される。
【0158】
次に、ステップS401で見つかったlevel集合に残りがあるか否かが判定される(ステップS407)。
前述のlevel 3の集合{4,7}の場合、まだノード7が残っている。従って、ステップS407の判定がYESとなり、ステップS403の処理に戻る。この結果、level 3の集合{4,7}からノード7が取り出される(ステップS403)。次に、1次元配列nmark上の上記ノードnodelvl=7に対応する配列位置の配列要素が、onを示す値に設定される(ステップS404)。更に、nodelvlノード=4に対するfirstdescendantのノードとして、fstdecs=5が設定される(ステップS405)(図14参照)。続いて、subtree chainに、ノードnodelvlが加えられる(ステップS406)。従って、subtree chainは、次のようになる。

subtree chain={4→7} ・・・(11)

【0159】
以上のステップS403からS407の処理により、タスクチェイン生成部103による前述のステップ6.の処理が実現される。
【0160】
次に、分岐ノード指示用1次元配列nmarkの配列要素がonとなっている分岐ノード又はリーフノードの何れかに辿り着くまで、エリミネーションツリーのルートノードから順に各ノードが辿られる。ここでは、図3の動作フローチャートで示したメモリ割付チェイン生成処理の場合と全く同様に、図8(c)に示される1次元のwork配列が用意され、ルートから同じ並列レベルのノードが辿られ、辿られたノードがwork配列に順次格納されてゆく。この処理は、図4のステップS309からS313までの処理によって実現される。これらの処理は、前述のメモリ割付チェイン生成処理における図3のステップS309からS313までの処理と同じ処理である。これらの処理の結果、図14に対応する図8の例においてwork配列に得られる結果は、前述した(7)式で示されるものとなる。
【0161】
以上のようにしてwork配列が確定したら、ステップS408にて、n=nodeendから1まで1ずつ減じられながら辿られた順の逆順で各work配列要素work(n)のノードが順次取り出される。そして、work配列から順次取り出されたノードが、第2のタスクチェインであるnode chainに加えられてゆく。この結果、node chainは、次のようになる。

node chain={11→12→13→14→15→16→17→18→19→20→10→21}
・・・(12)

【0162】
以上の処理により、第1のタスクチェインであるsubtree chainと、第2のタスクチェインであるnode chainによって、タスクの実行におけるノードの実行順が確定する。
【0163】
図5は、図1のLDL^T分解実行部104が実行する前述のステップ8.のLDL^T分解実行処理の詳細を示す動作フローチャートである。ここでは、subtree chain、node chainの順番で、各タスクチェインに接続されている各ノードがスレッドの並列数ずつ取り出され、各スレッドのタスクに割り当てられる。
【0164】
図5において、まず、ステップS501において、#thread 数だけタスクが生成される。以下、ステップS502からS512は、各スレッド毎に独立して実行される。
各スレッドでは、ステップS502において、変数snodeと変数nnodeの各値が0に初期設定される。
【0165】
次に、例えば第1のスレッドでは、ステップS503において、図1のタスクチェイン生成部103によって生成されたsubtree chainとnode chainがlock(ロック)される。これ以後、第1のスレッドがsubtree chainとnode chainがunlockするまでの間、第2のスレッドは、subtree chainとnode chainへのアクセスを待たされることになる。
【0166】
第1のスレッドでは、ステップS504にて、subtree chainにノードがあるか否かが判定される。
subtree chainにノードがあってステップS504の判定がYESの場合、第1のスレッドでは、ステップS505において、subtree chain の先頭ノードが取り出され、そのノード番号が変数snode に設定され、その後、subtree chainの次のノードが先頭に設定される。今、図8(a)に示されるデータ構造において、chain1がsubtree chainであったとした場合において、subtree chainが例えば前述の(11)式で示されるように得られている場合を考える。この場合、図8(a)のレジスタ801には、1次元配列800上のノード4に対応する配列位置が格納されている。また、1次元配列800上のノード4に対応する配列位置には、1次元配列800上のノード7に対応する配列位置が格納されている。1次元配列800上のノード7に対応する配列位置には、nullデータが格納されている。このような例において、第1のスレッドでは、ステップS505において、レジスタ801に格納されている配列位置が、ノード4のノード番号として変数snodeに設定される。その後、レジスタ801からアクセスできる1次元配列800上のノード4に対応する配列位置に格納されているノード7の配列位置が、新たにレジスタ801に設定し直される。
【0167】
第1のスレッドでは、ステップS505の処理の後、ステップS508において、subtree chainとnode chainに対するlockが解除(unlock)される。この結果、第1のスレッドと並列に実行されている第2のスレッドでは、subtree chainとnode chainへのアクセスが可能となる。
【0168】
続いて、第1のスレッドでは、ステップS509において、変数snodeの値が0であるか否かが判定される。
今、ステップS505にてsnodeにノード4のノード番号が設定されたため、ステップS509の判定はNOとなる。
【0169】
この結果、第1のスレッドでは、ステップS510にて、変数snodeに設定されているノード番号のノードをルートノードとするsubtreeの各構成ノードに対応する各panelの更新処理が実行される。即ち、前述した(1)式及び(2)式に基づくLDL^T分解処理が、順次実行される。上述の例で、変数snodeに設定されているノード番号に対応するノードがノード4である場合、このノード4をルートノードとするsubtreeの各構成ノードは、図14より、ノード1、2、3、及び4である。これらのノードに対するpanelの更新処理が、第1のスレッドにおいて順次実行される。このとき、前述したメモリ割付チェイン生成処理における図3のステップS315にて設定された図10に示されるようなメモリ割当て制御用のデータ群がアクセスされて、各ノードのメモリ割当てが制御される。
【0170】
以上の第1のスレッドによる制御処理と並列に、第2のスレッドにおいても同様の制御処理が実行される。
即ち、第2のスレッドで、ステップS503にて、subtree chainとnode chainがlockされる。これ以後、第2のスレッドがsubtree chainとnode chainがunlockするまでの間、第1のスレッドは、subtree chainとnode chainへのアクセスを待たされることになる。
【0171】
次に、第2のスレッドで、ステップS504にて、subtree chainにノードがあるか否かが判定される。
subtree chainにノードがあってステップS504の判定がYESの場合、第2のスレッドでは、ステップS505において、subtree chain の先頭ノードが取り出され、そのノード番号が変数snode に設定され、その後、subtree chainの次のノードが先頭に設定される。今、前述の第1のスレッドによるステップS505の処理によって、図8(a)のsubtree chainを示すレジスタ801に格納されている配列位置は、ノード4の次のノード7のノード番号を指している。この結果、第2のスレッドによりステップS505の処理では、ノード7のノード番号が変数snodeに設定される。その後、レジスタ801からアクセスできる1次元配列800上のノード7に対応する配列位置に格納されているnull値が、新たにレジスタ801に設定し直される。このnull値は、subtree chainにはこれ以上ノードが無いことを示している。
【0172】
第2のスレッドでは、ステップS505の処理の後、ステップS508において、subtree chainとnode chainに対するlockが解除(unlock)される。この結果、第2のスレッドと並列に実行されている第1のスレッドでは、subtree chainとnode chainへのアクセスが可能となる。
【0173】
続いて、第2のスレッドでは、ステップS509において、変数snodeの値が0であるか否かが判定される。
今、ステップS505にてsnodeにノード7のノード番号が設定されたため、ステップS509の判定はNOとなる。
【0174】
この結果、第2のスレッドでは、ステップS510にて、変数snodeに設定されているノード番号のノードをルートノードとするsubtreeの各構成ノードに対応する各panelの更新処理、即ちLDL^T分解処理が順次実行される。上述の例で、変数snodeに設定されているノード番号に対応するノードがノード7である場合、このノード7をルートノードとするsubtreeの各構成ノードは、図14より、ノード5、6、及び7である。これらのノードに対するpanelの更新処理が、第2のスレッドにおいて順次実行される。
【0175】
以上のようにして、第1のスレッドと第2のスレッドによって、subtree chainに登録されているノード4をルートノードとするsubtreeの構成ノード群に対するpanel更新処理と、ノード7をルートノードとするsubtreeの構成ノード群に対するpanel更新処理が並列に実行されることになる。このとき、前述のメモリ割付チェイン生成処理によって、ノード4をルートノードとするsubtreeの構成ノード群と、ノード7をルートノードとするsubtreeの構成ノード群は、それぞれ異なるメモリ格納領域(プール)に割り付けられている。従って、各subtreeの並列実行において同じメモリ格納領域にアクセスが集中してしまうという事態を回避することが可能となる。
【0176】
第1のスレッドでは、前述のステップS510の処理によってノード4をルートノードとするsubtreeの構成ノード群に対するpanel更新処理が終了すると、再びステップS502に移行し、変数snodeと変数nnodeがクリアされる。更に、第1のスレッドでは、ステップS503にて、subtree chainとnode chainがlockされる。
【0177】
続いて、第1のスレッドでは、ステップS504にて、subtree chainにノードがあるか否かが判定される。今、前述の第2のスレッドによるステップS505の処理によって、図8(a)のsubtree chainを示すレジスタ801には、subtree chainにはこれ以上ノードが無いことを示すnull値が設定されている。この結果、ステップS504の判定はNOとなって、第1のスレッドでは、ステップS506が実行される。
【0178】
ステップS506では、node chainにノードがあるか否かが判定される。
node chainにノードがあってステップS506の判定がYESの場合、第1のスレッドでは、ステップS507において、node chain の先頭ノードが取り出され、そのノード番号が変数nnode に設定され、その後、node chainの次のノードが先頭に設定される。今、図8(a)に示されるデータ構造において、chain2がnode chainであったとした場合において、node chainが例えば前述の(12)式で示されるように得られている場合を考える。この場合、図8(a)のレジスタ802には、1次元配列800上のノード11に対応する配列位置が格納されている。また、1次元配列800上のノード11に対応する配列位置には、1次元配列800上のノード12に対応する配列位置が格納されている。以下、node chainでの各ノードの接続順に従って、各ノードの配列位置にはその次に接続されるノードの配列位置が格納される。そして、最後のノードに対応する配列位置には、nullデータが格納されている。このような例において、第1のスレッドでは、ステップS507において、レジスタ802に格納されている配列位置が、ノード11のノード番号として変数nnodeに設定される。その後、レジスタ802からアクセスできる1次元配列800上のノード11に対応する配列位置に格納されているノード12の配列位置が、新たにレジスタ802に設定し直される。
【0179】
第1のスレッドでは、ステップS507の処理の後、ステップS508において、subtree chainとnode chainに対するlockが解除(unlock)される。
続いて、第1のスレッドでは、ステップS509において、変数snodeの値が0であるか否かが判定される。ここで、ステップS502にて変数snodeが0クリアされた後、ステップS504の判定はNOとなっているため、変数snodeの値は0のままであり、ステップS509の判定はYESとなる。
【0180】
この結果、第1のスレッドでは、ステップS511にて更に、変数nnodeの値が0であるか否かが判定される。今、変数nnodeには、ステップS507にてノード11のノード番号が格納されているため、ステップS511の判定はNOとなる。
【0181】
これにより、第1のスレッドでは、ステップS512において、変数nnodeに設定されているノード番号に対応するノード11に対応するpanelの更新処理、即ちLDL^T分解処理が実行される。このとき、前述したメモリ割付チェイン生成処理における図3のステップS315にて設定された図10に示されるようなメモリ割当て制御用のデータ群がアクセスされて、各ノードのメモリ割当てが制御される。
【0182】
以上の第1のスレッドによる制御処理と並列に、第2のスレッドにおいても更に並列処理が実行される。
即ち、第2のスレッドで、ステップS503にて、subtree chainとnode chainがlockされる。
【0183】
次に、第2のスレッドで、ステップS504にて、subtree chainにノードがあるか否かが判定される。今、図8(a)のsubtree chainを示すレジスタ801には、subtree chainにはこれ以上ノードが無いことを示すnull値が設定されている。この結果、ステップS504の判定はNOとなって、第2のスレッドで、ステップS506が実行される。
【0184】
ステップS506では、node chainにノードがあるか否かが判定される。
node chainにノードがあってステップS506の判定がYESの場合、第2のスレッドでは、ステップS507において、node chain の先頭ノードが取り出され、そのノード番号が変数nnode に設定され、その後、node chainの次のノードが先頭に設定される。今、前述の第1のスレッドによるステップS507の処理によって、図8(a)のnode chainを示すレジスタ802に格納されている配列位置は、ノード11の次のノード12のノード番号を指している。この結果、第2のスレッドによりステップS507の処理では、ノード12のノード番号が変数nnodeに設定される。その後、レジスタ802からアクセスできる1次元配列800上のノード12に対応する配列位置に格納されているノード13に対応する配列位置が、新たにレジスタ802に設定し直される。
【0185】
第2のスレッドでは、ステップS507の処理の後、ステップS508において、subtree chainとnode chainに対するlockが解除(unlock)される。
続いて、第2のスレッドでは、ステップS509において、変数snodeの値が0であるか否かが判定される。ここで、ステップS502にて変数snodeが0クリアされた後、ステップS504の判定はNOとなっているため、変数snodeの値は0のままであり、ステップS509の判定はYESとなる。
【0186】
この結果、第2のスレッドでは、ステップS511にて更に、変数nnodeの値が0であるか否かが判定される。今、変数nnodeには、ステップS507にてノード12のノード番号が格納されているため、ステップS511の判定はNOとなる。
【0187】
これにより、第2のスレッドでは、ステップS512において、変数nnodeに設定されているノード番号に対応するノード12に対応するpanelの更新処理、即ちLDL^T分解処理が実行される。
【0188】
以上のようにして、第1のスレッドと第2のスレッドによって、subtree chainに対する処理が終了した後に、node chainに登録されているノード11に対するpanel更新処理と、ノード12に対するpanel更新処理が並列に実行されることになる。これ以後も、node chainに登録されている2つずつのノードに対する各panel更新処理が第1及び第2のスレッドによって並列に実行される。このとき、前述のメモリ割付チェイン生成処理によって、node chainに順次登録されているノードは、サイクリックにそれぞれ異なるメモリ格納領域(プール)に割り付けられている。従って、各ノードの並列実行において同じメモリ格納領域にアクセスが集中してしまうという事態を回避することが可能となる。
【0189】
各スレッドでは、ステップS512の処理によって各ノードに対するpanel更新処理が終了すると、再びステップS502に移行する。そして、各スレッドでは、ステップS503からS512の一連の処理によって、node chainに登録されているノードが1つずつ取り出されながら、並列計算が実行される。
【0190】
ここで、図14の例では、例えばノード15のpanel更新時にはノード11、12、13、14が参照され、ノード16のpanel更新時にはノード12、13、14、15が参照される。この場合、番号が連続する各ノードは、それぞれ異なるメモリ格納領域(プール)に交互に割り付けられているため、1つのスレッドによる1つのノードに対するpanel更新処理においても、1つのメモリ格納領域にアクセスが集中してしまう事態を回避することが可能となる。
【0191】
以上の処理の結果、node chainに登録されているノードがなくなる、即ち図8(a)のレジスタ802からnull値が検出されると、ステップS506の判定がNO、ステップS509の判定がYES、ステップS511の判定もYESとなって、全てのLDL^T分解処理を終了する。
【0192】
以上の図5の動作フローチャートの処理により、LDL^T分解実行部104による前述のステップ8.の処理が実現される。
次に、並列に実行されるスレッド数が2から3に増やされた場合について説明する。
【0193】
メモリ割付けが行われるメモリ格納領域の数は前述の説明の場合と同様に2とする。即ち、前述の図3によるメモリ割付チェイン生成処理では、前述した事例の場合と同じ結果が出力される。
【0194】
スレッド数が3になると、図14のエリミネーションツリーの例において、レベル毎の分岐ノードの集合を探しても要素数が3以上のものはない。この結果、前述の図4によるタスクチェイン生成処理では、subtree chainは生成されず、node chainのみが生成される。この場合、work配列としては、次のようなものが生成される。

work={21|10,20|4,9,19|2,3,8,18|1,7,17|1,5,6,16|15|14|13|12|11}
・・・(13)

これより、node chainとしては、次のようなものが生成される。

node chain={11→12→13→14→15→16→6→5→1→17→7→1→18→8
→3→2→19→9→4→20→10→21} ・・・(14)

【0195】
前述の図5によるLDL^T分解実行処理における並列処理では、3個のスレッドに同じようにnode chainから各ノードが取り出されてそれぞれ独立して実行される。
最初、ノード11、12、13が3つのスレッドに割り当てられてpanel更新処理が実行され、空いたスレッドに次のノード14が割り当てられる。
【0196】
例えば、ノード11の更新処理では、ノード11のみがアクセスされる。ノード12の更新処理では、ノード11と12がアクセスされる。ノード13の更新処理では、ノード12と13がアクセスされる。これらのノードは、前述のメモリ割付チェイン生成処理によって割付チェインchain1と割付チェインchain2に交互に現れる。つまり、各ノードに対応するメモリ格納領域のliは、メモリ格納領域の前半と後半に分散して割り付けられている。このため、3個のスレッド全てが局所的なメモリ格納領域に集中することを回避することが可能となる。
【0197】
処理が進み、ノード18、8、3が並列実行されているときは、ノード18の更新処理ではノード14、15、16、17、18がアクセスされ、ノード8の更新処理ではノード5、7、8がアクセスされ、ノード3の更新処理ではノード3のみがアクセスされる。このとき、割付チェインchain1にノード3、15、17、8、割付チェインchain2にノード5、7、14、16、18というように、ほぼ均等に2つのメモリ格納領域に分散してノード割付けが行われている。このため、アクセスの集中を回避することが可能となる。
【0198】
上述の実施形態では、図1のメモリ割付チェイン生成部102によって実行される図3のメモリ割付チェイン生成処理では、レベル毎の分岐ノードの集合の要素数が連続にメモリデータを割り当てるセクション(メモリ格納領域)の数以上となるものがサーチされる。これに対して、連続にメモリデータを割り当てるセクションの数を超え、実行スレッド数に近い数をsubtree数とし、このsubtree数以上となるような分岐ノードの集合の要素数がサーチされるように構成されてもよい。このようなサーチにより、メモリ割付チェイン生成部102でのメモリ割付けの分散状態をタスクチェイン生成部103でのスレッド数の並列状態に合わせることができ、より効果的なメモリアクセス分散が可能となる。
【0199】
図11は、実施形態が適用されるハードウェアシステム構成の例を示す図(その1)である。
マルチコアCPU1100が、相互結合網(バス)1104を介して、複数のメモリモジュール1103と接続される。
【0200】
マルチコアCPU1100は、1つのCPUパッケージ内に、CPUコア+L1キャッシュ1101を複数封入したもので、L2キャッシュ・バスインタフェース1102は、各CPUコア+L1キャッシュ1101から共通に使用される。
【0201】
前述した各ノードが割り付けられるメモリ格納領域は、複数のメモリモジュール1103に分散して設定され、或いは、1つのメモリモジュール1103内の複数のバンクに分散して設定される。
【0202】
前述した並列計算を行うスレッドは、1つのマルチコアCPU1100内の各CPUコア+L1キャッシュ1101によってそれぞれ実行されるように構成することもできるし、1つのCPUコア+L1キャッシュ1101がマルチスレッド処理として実行するように構成することもできる。
【0203】
図12は、実施形態が適用されるハードウェアシステム構成の例を示す図(その2)である。
図12に示されるコンピュータシステムは、CPU1201、メモリ1202、入力装置1203、出力装置1204、外部記憶装置1205、可搬記録媒体1209が挿入される可搬記録媒体駆動装置1206、及びネットワーク接続装置1207を有し、これらがバス1208によって相互に接続された構成を有する。同図に示される構成は上記システムを実現できるコンピュータの一例であり、そのようなコンピュータはこの構成に限定されるものではない。
【0204】
CPU1201は、当該コンピュータ全体の制御を行う。メモリ1202は、プログラムの実行、データ更新等の際に、外部記憶装置1205(或いは可搬記録媒体1209)に記憶されているプログラム又はデータを一時的に格納するRAM等のメモリである。CUP1201は、プログラムをメモリ1202に読み出して実行することにより、全体の制御を行う。
【0205】
CPU1201は、図11に示されるように、マルチコアタイプのものであってもよい。また、メモリ1202は、図11に示されるように、複数のメモリモジュールから構成されてもよい。
【0206】
入力装置1203は、例えば、キーボード、マウス等及びそれらのインタフェース制御装置とからなる。入力装置1203は、ユーザによるキーボードやマウス等による入力操作を検出し、その検出結果をCPU1201に通知する。
【0207】
出力装置1204は、表示装置、印刷装置等及びそれらのインタフェース制御装置とからなる。出力装置1204は、CPU1201の制御によって送られてくるデータを表示装置や印刷装置に出力する。
【0208】
外部記憶装置1205は、例えばハードディスク記憶装置である。主に各種データやプログラムの保存に用いられる。
可搬記録媒体駆動装置1206は、光ディスクやSDRAM、コンパクトフラッシュ(登録商標)等の可搬記録媒体1209を収容するもので、外部記憶装置1205の補助の役割を有する。
【0209】
ネットワーク接続装置1207は、例えばLAN(ローカルエリアネットワーク)又はWAN(ワイドエリアネットワーク)の通信回線を接続するための装置である。
本実施形態によるシステムは、図1の各部に必要な機能を搭載したプログラムをCPU1201が実行することで実現される。そのプログラムは、例えば外部記憶装置1205や可搬記録媒体1209に記録して配布してもよく、或いはネットワーク接続装置1207によりネットワークから取得できるようにしてもよい。
【産業上の利用可能性】
【0210】
開示する技術は、有限要素法、偏微分方程式などの解析を行いシミュレーションを行う技術に利用することができる。
【符号の説明】
【0211】
101 分岐ノード集合検出部
102 メモリ割付チェイン生成部
103 タスクチェイン生成部
104 LDL^T分解実行部
1100 マルチコアCPU
1101 CPUコア+L1キャッシュ
1102 L2キャッシュ・バスインタフェース
1103 メモリモジュール
1104 相互結合網(バス)
1201 CPU
1202 メモリ
1203 入力装置
1204 出力装置
1205 外部記憶装置
1206 可搬記録媒体駆動装置
1207 ネットワーク接続装置
1208 バス
1209 可搬記録媒体

【特許請求の範囲】
【請求項1】
スパースな正値対象行列の連立1次方程式を解く演算処理を、該正値対象行列のコレスキー分解に先立ち入力行列の非零要素の構造を解析して得られるエリミネーションツリーを構成するスーパーノードを単位として実行する演算処理方法において、
前記エリミネーションツリーをそのルートノードからサーチすることにより、並列レベル毎の分岐ノードの集合を検出する分岐ノード集合検出処理ステップと、
前記分岐ノードの集合のうち、該集合の要素数が連続にメモリデータが割り当てられる記憶単位である複数のメモリ格納領域の数以上となる集合をサーチし、該サーチで得られる分岐ノードの集合に含まれる各分岐ノードをルートノードとする各サブツリー毎に、該サブツリーを構成するノード群に対する列ベクトルの演算結果を前記複数のメモリ格納領域から所定の選択規則によって選択したメモリ格納領域に割り付けるサブツリーメモリ格納領域割付けステップと
前記エリミネーションツリーを構成するノード群のうち、前記サーチで得られる分岐ノードの集合に対応する前記各サブツリーを構成するノード群を含まないノード群に対する前記列ベクトルの演算結果を、並列レベルが近接しているノード群の演算結果はそれぞれ異なるメモリ格納領域に割り付けられるように、前記複数のメモリ格納領域から所定の選択規則によって選択したメモリ格納領域に割り付けるノードメモリ格納領域割付けステップと、
を含むことを特徴とするスパースな正値対象行列の連立1次方程式の演算処理方法。
【請求項2】
前記分岐ノードの集合のうち、該集合の要素数が並列実行される複数のスレッドの数以上となる集合をサーチし、該サーチで得られる分岐ノードの集合に含まれる各分岐ノードをルートノードとする各サブツリーに関する情報を該各サブツリー単位で第1のタスクチェインであるサブツリーチェインに接続するサブツリーチェイン生成ステップと、
前記エリミネーションツリーを構成するノード群のうち、前記スレッドに関するサーチで得られる分岐ノードの集合に対応する前記各サブツリーを構成するノード群を含まないノード群を、前記エリミネーションツリーのリーフノードからルートノードに向かう順でかつ並列レベル毎にまとまるようにして、第2のタスクチェインであるノードチェインに接続するノードチェイン生成ステップと、
を更に含み、
前記各スレッドは、前記サブツリーチェインに接続されている各サブツリーに関する情報を登録順に選択して該情報に対応するサブツリーを構成するノード群に対する前記列ベクトルの演算を実行し、前記サブツリーチェインで選択すべきエントリがなくなったら、前記ノードチェインに接続されている各ノードに対する前記列ベクトルの演算を登録順に実行する、
ことを特徴とする請求項1に記載のスパースな正値対象行列の連立1次方程式の演算処理方法。
【請求項3】
スパースな正値対象行列の連立1次方程式を解く演算処理を、該正値対象行列のコレスキー分解に先立ち入力行列の非零要素の構造を解析して得られるエリミネーションツリーを構成するスーパーノードを単位として実行する演算処理装置において、
前記エリミネーションツリーをそのルートノードからサーチすることにより、並列レベル毎の分岐ノードの集合を検出する分岐ノード集合検出処理部と、
前記分岐ノードの集合のうち、該集合の要素数が連続にメモリデータが割り当てられる記憶単位である複数のメモリ格納領域の数以上となる集合をサーチし、該サーチで得られる分岐ノードの集合に含まれる各分岐ノードをルートノードとする各サブツリー毎に、該サブツリーを構成するノード群に対する列ベクトルの演算結果を前記複数のメモリ格納領域から所定の選択規則によって選択したメモリ格納領域に割り付けるサブツリーメモリ格納領域割付け部と
前記エリミネーションツリーを構成するノード群のうち、前記サーチで得られる分岐ノードの集合に対応する前記各サブツリーを構成するノード群を含まないノード群に対する前記列ベクトルの演算結果を、並列レベルが近接しているノード群の演算結果はそれぞれ異なるメモリ格納領域に割り付けられるように、前記複数のメモリ格納領域から所定の選択規則によって選択したメモリ格納領域に割り付けるノードメモリ格納領域割付け部と、
を含むことを特徴とするスパースな正値対象行列の連立1次方程式の演算処理装置。
【請求項4】
前記分岐ノードの集合のうち、該集合の要素数が並列実行される複数のスレッドの数以上となる集合をサーチし、該サーチで得られる分岐ノードの集合に含まれる各分岐ノードをルートノードとする各サブツリーに関する情報を該各サブツリー単位で第1のタスクチェインであるサブツリーチェインに接続するサブツリーチェイン生成部と、
前記エリミネーションツリーを構成するノード群のうち、前記スレッドに関するサーチで得られる分岐ノードの集合に対応する前記各サブツリーを構成するノード群を含まないノード群を、前記エリミネーションツリーのリーフノードからルートノードに向かう順でかつ並列レベル毎にまとまるようにして、第2のタスクチェインであるノードチェインに接続するノードチェイン生成部と、
を更に含み、
前記各スレッドは、前記サブツリーチェインに接続されている各サブツリーに関する情報を登録順に選択して該情報に対応するサブツリーを構成するノード群に対する前記列ベクトルの演算を実行し、前記サブツリーチェインで選択すべきエントリがなくなったら、前記ノードチェインに接続されている各ノードに対する前記列ベクトルの演算を登録順に実行する、
ことを特徴とする請求項3に記載のスパースな正値対象行列の連立1次方程式の演算処理装置。
【請求項5】
スパースな正値対象行列の連立1次方程式を解く演算処理を、該正値対象行列のコレスキー分解に先立ち入力行列の非零要素の構造を解析して得られるエリミネーションツリーを構成するスーパーノードを単位として実行するコンピュータに、
前記エリミネーションツリーをそのルートノードからサーチすることにより、並列レベル毎の分岐ノードの集合を検出する分岐ノード集合検出処理ステップと、
前記分岐ノードの集合のうち、該集合の要素数が連続にメモリデータが割り当てられる記憶単位である複数のメモリ格納領域の数以上となる集合をサーチし、該サーチで得られる分岐ノードの集合に含まれる各分岐ノードをルートノードとする各サブツリー毎に、該サブツリーを構成するノード群に対する列ベクトルの演算結果を前記複数のメモリ格納領域から所定の選択規則によって選択したメモリ格納領域に割り付けるサブツリーメモリ格納領域割付けステップと
前記エリミネーションツリーを構成するノード群のうち、前記サーチで得られる分岐ノードの集合に対応する前記各サブツリーを構成するノード群を含まないノード群に対する前記列ベクトルの演算結果を、並列レベルが近接しているノード群の演算結果はそれぞれ異なるメモリ格納領域に割り付けられるように、前記複数のメモリ格納領域から所定の選択規則によって選択したメモリ格納領域に割り付けるノードメモリ格納領域割付けステップと、
を実行させるためのプログラム。
【請求項6】
前記分岐ノードの集合のうち、該集合の要素数が並列実行される複数のスレッドの数以上となる集合をサーチし、該サーチで得られる分岐ノードの集合に含まれる各分岐ノードをルートノードとする各サブツリーに関する情報を該各サブツリー単位で第1のタスクチェインであるサブツリーチェインに接続するサブツリーチェイン生成ステップと、
前記エリミネーションツリーを構成するノード群のうち、前記スレッドに関するサーチで得られる分岐ノードの集合に対応する前記各サブツリーを構成するノード群を含まないノード群を、前記エリミネーションツリーのリーフノードからルートノードに向かう順でかつ並列レベル毎にまとまるようにして、第2のタスクチェインであるノードチェインに接続するノードチェイン生成ステップと、
を更に含み、
前記各スレッドは、前記サブツリーチェインに接続されている各サブツリーに関する情報を登録順に選択して該情報に対応するサブツリーを構成するノード群に対する前記列ベクトルの演算を実行し、前記サブツリーチェインで選択すべきエントリがなくなったら、前記ノードチェインに接続されている各ノードに対する前記列ベクトルの演算を登録順に実行する、
ことを特徴とする請求項5に記載のプログラム。

【図1】
image rotate

【図2】
image rotate

【図3】
image rotate

【図4】
image rotate

【図5】
image rotate

【図6】
image rotate

【図7】
image rotate

【図8】
image rotate

【図9】
image rotate

【図10】
image rotate

【図11】
image rotate

【図12】
image rotate

【図13】
image rotate

【図14】
image rotate


【公開番号】特開2010−224682(P2010−224682A)
【公開日】平成22年10月7日(2010.10.7)
【国際特許分類】
【出願番号】特願2009−68957(P2009−68957)
【出願日】平成21年3月19日(2009.3.19)
【出願人】(000005223)富士通株式会社 (25,993)
【Fターム(参考)】