JP2009199430A - ベクトル積の並列処理方法 - Google Patents

ベクトル積の並列処理方法 Download PDF

Info

Publication number
JP2009199430A
JP2009199430A JP2008041498A JP2008041498A JP2009199430A JP 2009199430 A JP2009199430 A JP 2009199430A JP 2008041498 A JP2008041498 A JP 2008041498A JP 2008041498 A JP2008041498 A JP 2008041498A JP 2009199430 A JP2009199430 A JP 2009199430A
Authority
JP
Japan
Prior art keywords
matrix
calculation result
thread
update
array
Prior art date
Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
Granted
Application number
JP2008041498A
Other languages
English (en)
Other versions
JP5262177B2 (ja
Inventor
Makoto Nakanishi
誠 中西
Current Assignee (The listed assignees may be inaccurate. Google has not performed a legal analysis and makes no representation or warranty as to the accuracy of the list.)
Fujitsu Ltd
Original Assignee
Fujitsu Ltd
Priority date (The priority date is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the date listed.)
Filing date
Publication date
Application filed by Fujitsu Ltd filed Critical Fujitsu Ltd
Priority to JP2008041498A priority Critical patent/JP5262177B2/ja
Publication of JP2009199430A publication Critical patent/JP2009199430A/ja
Application granted granted Critical
Publication of JP5262177B2 publication Critical patent/JP5262177B2/ja
Active legal-status Critical Current
Anticipated expiration legal-status Critical

Links

Landscapes

  • Complex Calculations (AREA)

Abstract

【課題】圧縮列格納法を用いたスパース行列とベクトルとの積を効率よく並列に処理する並列処理方法を提供する。
【解決手段】上記課題を解決するために、演算割り当て範囲における部分行列についての行列のベクトル積の演算処理を各スレッドに実行させ、演算結果が更新割り当て範囲か否かを判別し、当該演算結果が、更新割り当て範囲の場合には、行列と列ベクトルとの積を記憶する演算結果記憶手段に記憶し、更新割り当て範囲でない場合には、行列と列ベクトルとの積を一時的に記憶する演算結果退避手段に記憶させ、各スレッドに演算結果退避手段から他のスレッドが算出した更新割り当て範囲の演算結果を読み出させ、演算結果記憶手段に記憶されている演算結果を更新させる。
【選択図】図4

Description

本発明は、圧縮列格納法を用いたスパース行列とベクトルとの積を並列に処理する並列処理方法に関する。
数値解析を行なう場合などに使用するスパース行列のデータ記憶領域への格納方法(以下、単に「スパース行列の格納方法」という)には、いろいろな方法が提案されている。有限要素法などでは、圧縮列格納法(Harwell−boeing format storage method)といわれる格納方法が広く使用されている。
圧縮列格納法とは、スパース行列の列ベクトルにある非ゼロ要素を圧縮し、圧縮した列ベクトルを順次1次元配列に格納する格納方法である。
例えば、n行n列のスパース行列(nは自然数)を行列mat、行列matの非ゼロ要素の総数をnz(nzは自然数)とすると、行列matは、nz個の要素からなる1次元配列aに格納される。
同時に、行列matの各列における先頭の非ゼロ要素が配列aの何番目の要素に格納されているかを示す情報が、n個の要素からなる1次元配列nfcnzに格納される。
さらに、配列aに格納された各要素が、行列matの何番目の行ベクトルに属するかを示す情報が、nz個の要素からなる1次元配列nrowに格納される。
したがって、例えば、行列matの第k列目(kは自然数)の非ゼロ要素は、配列aのnfcnz(k)番目からnfcnz(k+1)−1番目の要素に格納される。そして、各要素が属する行ベクトルの行番号は、配列nrowのnfcnz(k)番目からnfcnz(k+1)−1番目の要素に格納される。
ここで、行列matと列ベクトルxとの積yを求める場合、i番目の行の要素y(i)は、1≦j≦nについて(i,jは自然数)、
y(i)=y(i)+mat(i,j)*x(j)
の計算を行なうことで得られる。したがって、1≦j≦nの要素について上式の計算を行なうことにより、i番目の行の要素y(i)の計算をすることができる。
上述の演算を行なう簡単な方法としては、例えば、各CPUにyと同じ記憶領域y1〜ym(mはCPUの数を表す自然数)を割り当てるとともに、列の総数nを均等に分割して各CPUに割り当て、CPU毎に当該分割した行列matの部分行列と行の総数nを均等に分割して得る行列xの部分行列とについてベクトル積を算出し、結果を領域y1〜ymに格納し、最後にこれらの結果を加え合わせる方法がある。この演算方法は、簡単であるが、計算時間がかかりすぎてしまうという問題があった。
また、領域yi(i=1、2、・・・、m)のバンド幅band(各列で対角要素の位置から最も離れた非ゼロ要素までの距離。例えば、対角要素を第i列目の対角要素mat(i,i)と同じ列にある最も離れた非ゼロ要素がmat(j,i)である場合のバンド幅はabs(j−i)となる。)を考慮し、2*band+nn(nnはnをCPU数mで均等に分割した大きさ(n+m−1)/m)に演算する範囲を制限することも可能であるが、バンド幅が大きく境界との間に非ゼロ要素がない場合には、大きな領域を使用することになる。そのため、上述したように、yiに格納された演算結果を加算して積yを求める処理にコストがかかってしまい、並列化処理の効果が低下してしまうという問題があ
った。
上記技術に関連して、特許文献1には、反復解法により連立一次方程式を解くメモリ分散型並列計算機において、多様なデータ格納方法に対応して効率的な並列処理を行う反復解法について開示されている。
また、特許文献2には、プロセッサ間の同期回数を減らして、共有メモリベクトル並列計算機上でランダムスパース行列とベクトルとの積を高速に実行する行列ベクトル積演算システムについて開示されている。
特開平09−212483号公報 特開2001−209631号公報
本発明は、上述した問題に鑑みてなされたものであり、その解決しようとする課題は、圧縮列格納法を用いたスパース行列とベクトルとの積を効率よく並列に処理する並列処理方法を提供することである。
上記課題を解決するために、演算装置に、複数のスレッドを同時並列的に使用して行列と列ベクトルとの積を算出する演算方法であって、前記行列を所定の範囲で分割して部分行列を生成し、該部分行列についての行列のベクトル積の演算処理を、前記スレッド毎に割り当てる演算割り当て範囲を決定する演算割り当て範囲決定処理と、前記スレッドが算出した演算結果から、前記行列と列ベクトルとの積の一部を求める演算結果の更新処理を、前記スレッド毎に割り当てる更新割り当て範囲を決定する更新割り当て範囲決定処理と、前記演算割り当て範囲における前記部分行列を、前記行列を圧縮列格納法にしたがって圧縮して記憶する行列記憶手段から読み出し、該部分行列についての行列のベクトル積の演算処理を前記スレッドに実行させるベクトル演算処理と、該演算結果が前記更新割り当て範囲か否かを判別し、前記更新割り当て範囲の場合には前記演算結果を、前記行列と列ベクトルとの積を記憶する演算結果記憶手段に記憶し、前記更新割り当て範囲でない場合には前記演算結果を、前記行列と前記列ベクトルとの積を一時的に記憶する演算結果退避手段に記憶させる演算結果振り分け処理と、該演算結果退避手段から他のスレッドが算出した更新割り当て範囲の演算結果を読み出し、前記演算結果記憶手段に記憶されている演算結果を更新する演算結果更新処理と、を実行させる。
上記演算方法によると、各スレッドは、演算割り当て範囲決定処理で割り当てた演算割り当て範囲の演算処理を並列的に実行する。そして、演算結果が更新割り当て範囲の場合には行列と演算結果記憶手段に記憶し、演算結果が更新割り当て範囲でない場合には演算結果退避手段に記憶させる。そのため、各スレッドは、自身に割り当てられた更新割り当て範囲の更新処理についても並列的に実行することが可能となる。その結果、スパース行列と列ベクトルとの積を効率よく並列に処理することが可能となる。
以上に説明したように、本発明によると、圧縮列格納法を用いたスパース行列とベクトルとの積を効率よく並列に処理する並列処理方法を提供することが可能となる。
以下、本発明の実施形態について、図1〜図8に基づいて説明する。
(本実施例に係る並列処理の概要)
説明を簡単にするために、下記に示す4行4列の行列matと4行1列の列ベクトルx
のベクトル積における並列処理(並列処理が可能な2つのCPU(CPU#1、CPU#2)を有する場合)について説明する。
なお、本実施例に係る並列処理を、行列matが4行4列の場合に限定する趣旨ではない。必要に応じて、n行n列の行列matについて下記の処理を行なうことで同様の効果を得ることができるのは当然である。また、並列処理を行なうCPUの数についても2つに限定する趣旨ではなく、必要に応じて2以上のCPUを使用してもよい。
・・・ (1)
・・・ (2)
yを4行1列の列ベクトルとすると、行列matと列ベクトルxのベクトル積は、次式によって求められる。
・・・ (3)
ここで、行列matの列を2つに分割した下記の4行2列の部分行列m1、m2と、列ベクトルxの行を2つに分割した下記に示す2行1列の部分列ベクトルx1、x2を用いると、
・・・ (4)
・・・ (5)
式(3)は、下記のように変形することができる。
・・・ (6)
本実施例に係る行列のベクトル積では、図1に示すようにm1*x1’の演算処理をCPU#1に割り当て、m2*x2’の演算処理をCPU#2に割り当てる。このように各CPUに割り当てられた演算処理を、以下「演算割り当て範囲」という。なお、演算装置100が生成する各スレッドに当該演算処理を割り当てた場合も同様である。
また、各CPUによる演算結果yの更新処理において、(y1,y2)の更新処理をCPU#1に割り当て、(y3,y4)の更新処理をCPU#2に割り当てる。このように各CPUに割り当てられた更新処理を、以下「更新割り当て範囲」という。なお、演算装置100が生成する各スレッドに当該更新処理を割り当てた場合も同様である。
例えば、CPU#1は、CPU#1自身による演算「a1,1*x1+a1,2*x2」の結果と、CPU#2による演算「a1,3*x3+a1,4*x4」の結果と、からy1を求める(y1の値を更新する)。同様に、CPU#1は、CPU#1自身による演算「a2,1*x1+a2,2*x2」の結果と、CPU#2による演算「a2,3*x3+a2,4*x4」の結果と、からy2を求める(y2の値を更新する)。
したがって、CPU#1自身による演算「a1,1*x1+a1,2*x2」および「a2,1*x1+a2,2*x2」、CPU#2による演算「a1,3*x3+a1,4*x4」および「a2,3*x3+a2,4*x4」は、CPU#1の更新割り当て範囲となる。
同様に、CPU#2は、CPU#1による演算「a3,1*x1+a3,2*x2」の結果と、CPU#2自身による演算「a3,3*x3+a3,4*x4」の結果と、から
y3を求め、CPU#1による演算「a4,1*x1+a4,2*x2」の結果と、CPU#2自身による演算「a4,3*x3+a4,4*x4」の結果と、からy4を求めるので、
CPU#1による演算「a3,1*x1+a3,2*x2」および「a4,1*x1+a4,2*x2」、CPU#2自身による演算「a3,3*x3+a3,4*x4」および「a4,3*x3+a4,4*x4」は、CPU#2の更新割り当て範囲となる。
なお、並列処理を割り当て可能なCPUをm個有する場合には、行列matの列をm分割したm個の部分行列と、列ベクトルxをm分割したm個の部分行列を用いればよい。この場合、各部分行列のベクトル積の演算処理を、各CPUに割り当てればよい。また、行列yの行をm分割した各部分行列の更新処理を、各CPUに割り当てればよい。なお、演算装置100が生成する各スレッドに対して演算処理、更新処理を割り当ててもよい。
(本実施例に係る圧縮列格納法)
図2は、本実施例に係る圧縮列格納法の説明をする図である。
図2では、式(1)に示した行列matを具体化した下記のスパース行列matを圧縮列格納法により記憶装置に記憶する場合について説明する。なお、当該圧縮列格納法を当該スパース行列の場合に限定する趣旨でないのは当然である。
・・・ (7)
行列matを圧縮列格納法を用いて記憶装置に記憶するためには、図2に示す1次元配列a、nfcnzおよびnrow(すなわち、配列a、nfcnzおよびnrowを確保する記憶領域)を使用する。
配列aには、行列matの列の非ゼロ要素を圧縮して順次格納する。例えば、行列matの第1列は(1 0 2 0)であるから、0を除く要素「1」、「2」を配列aに順次格納する。同様に、行列matの第2列は(0 −4 0 1)であるから、0を除く要素「−4」、「1」を配列aに順次格納する。
配列nrowには、配列aに格納された要素が属する行数を格納する。例えば、配列aの第1、2番目の要素には、行列matの第1列の非ゼロ要素「1」、「2」が圧縮されて格納されるので、配列nrowには、その要素の属する行番号「1」、「3」を格納する。
配列nfcnzには、行列matにおける各列の最初の非ゼロ要素が格納されている配列a(または、配列nrow)の要素番号を格納する。例えば、行列matにおける第1列目の最初の非ゼロ要素は「1」である。この要素は、配列aの第1番目の要素に格納されているので、配列nfcnzの第1番目の要素には、「1」を格納する。同様に、行列matにおける第2列目の最初の非ゼロ要素は「−4」である。この要素は、配列aの第3番目の配列に格納されているので、配列nfcnzの第2番目の配列には、「3」を格納する。
ここで、n行n列の行列matを考える。この行列matに非ゼロ要素がnz個含まれる場合、配列nfcnzは大きさがn+1の1次元配列となり、配列aおよびnrowは大きさがnzの1次元配列となる。
なお、配列nfcnz(n+1)には、計算機の都合等を考慮して行列matの仮想要素が格納される配列番号(例えば、図2に示す行列matの要素mat(1,5)が格納される配列aの配列番号)が格納されるが、必須ではない。
また、これらの配列についてメモリ等の記憶装置に記憶領域を確保する場合、配列aは行列matの要素と同じデータ型(例えば、倍精度実数型など)の1次元配列として領域を確保し、配列nfcnzおよびnrowは整数型の1次元配列として領域を確保すればよい。
(第1の実施例)
図3は、本実施例に係る行列ベクトル積の演算の概要を説明する図である。なお、図3に示す1次元配列w、2次元配列iw、3次元配列nentryは、図2に示した行列matについて演算を行なう場合の例を示しているが、これに限定する趣旨でないのは当然である。
配列wは、配列aに格納されている要素について、次式による演算結果を格納する1次元配列である。以下、「演算結果退避領域」という。
・・・ (8)
したがって、配列wは配列aと同じ大きさ(同じ構成)の1次元配列とすればよい。なお、本実施例では、更新割り当て範囲に属する演算結果については、配列wに格納せずに、演算結果を格納する配列y(以下、「演算結果記憶領域」という)に格納するので、配列aより小さい大きさであってもよい。
配列iwは、配列wに格納されている要素について、式(8)による演算を行なった場合の要素ai,jが属する行番号(すなわち、nrow(i)に格納されている値)を格納する2次元配列である。
ここで、配列iwの1要素は、次の要素の位置を示す位置データを格納する領域iw(1,i)(以下、「位置情報領域」という)と、上記nrow(i)の値を格納する領域iw(2,i)(以下、「データ領域」という)と、で構成される。本実施例では、両領域ともに整数型として記憶領域を確保する。そして、複数の要素が連なってチェイン構造となる。以下、この配列iwの1要素iw(1:2,i)を「チェイン」という。
配列nentryは、更新割り当て範囲毎に、演算割り当て範囲の演算結果w(i)に対応するチェインiw(1:2,i)が格納されている先頭位置情報と終端位置情報を格納する。
本実施例では、図1で示したように更新割り当て範囲が2つ、演算割り当て範囲が2つなので、配列nentryは図3に示す2×2の2次元配列となる。ただし、各要素は2つの要素で構成され、1つの要素は、チェインiw(1,i)の先頭位置情報を格納する領域nentry(1,i,j)(以下、「先頭位置領域」という)であり、もう1つの要素は、チェインiw(i)の終端位置情報を格納する領域nentry(2,i,j)
(以下、「終端位置領域」という)である。本実施例では、両領域とも整数型として記憶領域を確保する。
したがって、配列nentryは、
(1)nentry(1:2,1,1)に、CPU#1の更新割り当て範囲かつCPU#1の演算割り当て範囲、
(2)nentry(1:2,1,2)に、CPU#1の更新割り当て範囲かつCPU#2の演算割り当て範囲、
(3)nentry(1:2,2,1)に、CPU#2の更新割り当て範囲かつCPU#1の演算割り当て範囲、
(4)nentry(1:2,2,2)に、CPU#2の更新割り当て範囲かつCPU#2の演算割り当て範囲、の演算結果に対応するチェインiwの先頭位置情報と終端位置情報を格納する。
なお、本実施例では、更新割り当て範囲かつ演算割り当て範囲の演算結果は、演算結果を格納する配列yに格納する。そのため、本実施例に係るnentry(1:2,1,1)とnentry(1:2,2,2)は使用しない。そこで、各先頭位置領域nentry(1,1,1)とnentry(1,2,2)には、データが存在しない旨を示すデータ(図3の例では、「0」、以下「ターミナル情報」という)を格納する。
ここで、例えば、式(2)に示した列ベクトルxが次式の場合について、行列matと列ベクトルxのベクトル積を考える。
・・・ (9)
CPU#1は、演算割り当て範囲における式(2)の演算を実行する。そして、当該演算が更新割り当て範囲である場合には、演算結果を格納する配列yに演算結果を格納し、当該演算が更新割り当て範囲でない場合には、演算結果を配列wに格納する。
例えば、CPU#1は、演算結果「1」(=a(1)×x(1))、「−8」(=a(3)×x(2))を、それぞれ配列y(1)、y(2)に格納し、演算結果「2」(=a(2)×x(1))、「2」(=a(4)×x(2))を、それぞれ配列w(1)、w(2)に格納する。
さらに、CPU#1は、演算結果「2」(=a(2)×x(1))を配列w(1)に格納する時、新たなチェインのデータ領域iw(2,1)に、a(2)に対応するnrow(2)の値を格納し、当該チェインの位置情報領域iw(1,1)にターミナル情報を格納する。
同様に、CPU#1は、演算結果「2」(=a(4)×x(2))を配列w(2)に格納する時、チェインの位置情報領域iw(1,1)に新たなチェインのデータ領域の位置情報3を格納する。そして、当該新たなチェインのデータ領域iw(2,2)に、a(4
)に対応するnrow(4)の値を格納し、当該チェインの位置情報領域iw(1,2)にターミナル情報を格納する。
CPU#2も同様の処理を行なう。
各CPUが自身に割り当てられた演算割り当て範囲について演算を完了すると、各CPUは、自身に割り当てられた更新割り当て範囲について、配列nentryを参照する。そして、当該nentryの先頭位置領域が示すチェインiwから、当該nentryの終端位置領域が示すチェインiwまで、たどりながらチェインiwのデータ領域を参照する。そして、当該データ領域に格納されている行番号に基づいて、各チェインiwに対応する配列wに格納されている演算結果を、配列yのいずれの要素に加算するか判断し、該当する配列yの要素に加算する。
例えば、CPU#1は、nentry(1,1,2)の先頭位置領域を参照する。そして、配列iwの3番目のチェインのデータ領域を参照する。すると、行番号が第1行とわかるので、当該チェインに対応する演算結果w(3)は、y(1)に加算するものと判断し、y(1)の値に演算結果w(3)を加算した値をy(1)に格納する。以上の処理を、チェインの終端まで行なう。CPU#2についても同様である。
以上の処理によって、行列matと列ベクトルxとのベクトル積の演算結果を配列yに得ることができる。
(本実施例に係る行列のベクトル積の演算の具体的な説明)
以下、n行n列の行列matとn行1列の列ベクトルxの行列ベクトル積y=mat*xについて説明する。
図4は、本実施例に係る行列のベクトル積の演算の処理を示すフローチャートである。
ステップS401において、演算装置100は、行列matの列の総数nを演算処理の割り当て可能なCPU数mで均等に分割したn行(n/m)列の部分行列mat’1、mat’2、mat’3、・・・、mat’m、を生成する。
同様に、列ベクトルxの行の総数nをmで均等に分割した(n/m)行1列の部分列ベクトルx’1、x’2、x’3、・・・、x’m、を生成する。
そして、部分行列ベクトル積mat’k*x’kの処理をCPU#k(kは1以上m以下の自然数)に割り当てる。この時、例えば、行列ベクトル積mat’k*x’kが、CPU#kの演算割り当て範囲となる。
ステップS402において、演算装置100は、行列ベクトル積の演算結果を格納する行列yを演算処理を割り当て可能なCPU数mで均等に分割し、y(m*(k−1)+1:m*k)の更新処理をCPU#kに割り当てる。この時、例えば、y(m*(k−1)+1:m*k)の更新処理がCPU#kの更新割り当て範囲となる。
ここで、並列実行するスレッドの総数をnumthrd(=m)とし、各スレッドに割り当てられるスレッド番号(1〜m)をnothrdとする。
ステップS403において、各スレッドは、自身に割り当てられた演算割り当て範囲について行列ベクトル積の計算(mat(i,j)*x(j))を行なう。
ステップS404において、スレッド番号nothrdのスレッドによる演算結果が自身の更新割り当て範囲y(m*(nothrd−1):m*nothrd)の要素の場合、当該スレッドは、処理をステップS405に移行し、当該演算結果を該当するyの要素に格納する。また、既に値が格納されている場合には、当該値に演算結果を加算した値にyの要素を更新する。
ステップS404において、スレッド番号nothrdのスレッドによる演算結果が自身の更新割り当て範囲y(m*(nothrd−1):m*nothrd)以外のyの要素の場合、当該スレッドは、処理をステップS406に移行する。そして、当該スレッドは、配列aと同じ大きさの作業領域の配列wに、自身が担当する配列aの領域と同じ領域を対応付け、当該領域の先頭から順に演算結果を格納する。
ステップS407において、当該スレッドは、チェインを構成する1次元配列chainを複数格納する記憶領域であって、chain(1)には次のチェインの先頭位置を示す位置情報を格納しchain(2)には当該演算結果に係る行列matの計算要素の行数を格納する配列iwに、チェインを追加し、当該演算結果に係る行列matの計算要素の行数を格納する。
ステップS408において、当該スレッドは、更新割り当て範囲毎に、各演算割り当て範囲における演算より配列iwに格納されたチェインの先頭位置と終端位置とを配列nentryに格納する。
例えば、スレッド番号nothrdのスレッドによる演算結果が、スレッド番号kのスレッドに割り当てられた更新割り当て範囲である場合、当該スレッドは、配列iwにチェインを追加して当該演算結果に係る行列matの計算要素の行数を格納する。そして、当該チェインの先頭位置をnentry(1,k,nothrd)に、当該チェインの終端位置をnentry(2,k,nothrd)に、格納する。
なお、上述の配列w、iwおよびnentryは、配列a、nfcnz、nrowと同様に共有メモリに配置すればよい。
ステップS409において、当該スレッドは、自身に割り当てられた演算割り当て範囲について、行列のベクトル積の演算を全て実行したか否かを判別する。そして、まだ、演算割り当て範囲の全ての演算を完了していない場合、当該スレッドは、処理をステップS403に移行し、ステップS403〜S409の処理を繰り返す。また、演算割り当て範囲の全ての演算を完了した場合、当該スレッドは、処理をステップS410に移行する。
ステップS410において、当該スレッドは、バリア同期をとって、他のスレッドが自身に割り当てられた演算割り当て範囲の処理を完了するまで処理を停止する。
ステップS411において、スレッド番号がnothrdのスレッドは、他のスレッドに割り当てられた演算割り当て範囲、かつ自身のスレッドに割り当てられた範囲について、配列nentryがポイントする先頭チェインから終端チェインまでを参照し、当該チェインに格納された位置情報pに対応するw(p)から演算結果を取得し、当該チェインに格納された行数qに対応するy(q)に加算する。
以上の処理において、例えば、演算割り当て範囲決定処理はステップS401に対応し、更新割り当て範囲決定処理はステップS402に対応し、ベクトル演算処理はステップS403に対応し、演算結果振り分け処理はステップS404〜408に対応し、演算結果更新処理はステップ411に対応する。
また、例えば、行列記憶手段、演算結果退避手段、演算割り当て範囲決定手段、更新割り当て範囲決定手段、ベクトル演算処理手段、演算結果振り分け手段および演算結果更新手段は、図8に示す各CPUが、メモリモジュール等に配置された所定のプログラムに記載された命令を実行することによって実現される。
図5A〜5Cは、本実施例に係る行列のベクトル積の演算処理の具体例を示すフローチ
ャートである。図5A〜5Cに示すフローチャートは、n行n列のスパース行列matとn行1列の列ベクトルxとの演算処理を示す。
なお、以下の処理において、行列matの非ゼロ要素の総数をnz、並列実行するスレッドの数をnumthrdとする。また、行列matを圧縮列格納方式にしたがって非ゼロ要素を格納した1次元配列をa(nz)とする。また、配列a(nz)に格納した各要素の行番号を、当該要素を格納したa(nz)の配列番号と同じ配列番号の位置に格納する1次元配列をnrow(nz)とする。また、行列matの各列における最初の非ゼロ要素が格納されているa(nz)の位置を格納する1次元配列をnfcz(n)とする。
また、列ベクトルxを格納する1次元配列をx(n)、演算結果を格納する1次元配列をy(n)とする。そして、図3で説明した作業領域を1次元配列w(nz)、2次元配列iw(2,nz)、3次元配列nentry(2,numthrd,numthrd)とする。
ステップS500において、演算装置100は、例えば、行列matと列ベクトルxが入力されると、行列matを圧縮列格納方式にしたがって配列aに格納する。そして、以下に示す行列のベクトル積mat*xの演算を開始する。
ステップS501において、演算装置100は、並列処理を実行するスレッドをnumthrdだけ確保する。さらに、演算装置100は、配列nentry(2,numthrd,numthrd)の領域を共有メモリに確保する。そして、演算装置100は、nentry=0により当該ポインタをゼロクリアする。
ステップS502において、演算装置100は、ステップS501で確保したスレッド数numthrdのスレッドを生成する。そして、演算装置100は、各スレッドにスレッド番号nothrd(1〜numthrd)を割り当てる。
ステップS503において、スレッドは、行列matの次数nをnumthrdで均等に分割する。そして、各スレッドが分担する区分js〜jeを決定する。この時、スレッドは、次式によりjsおよびjeを算出する。
nn = (n+numthrd−1)/numthrd
js = nn*(nothrd−1)
je = min(n,nn*nothrd)
例えば、スレッド番号kのスレッドの演算割り当て範囲は、行列matの部分行列mat(1:n,nn*(k−1):min(n,nn*k))と、列ベクトルx(n,1)の部分列ベクトルをx(nn*(k−1):min(n,nn*k),1)とすると、
mat(1:n,nn*(k−1):min(n,nn*k))*x(nn*(k−1):min(n,nn*k),1) ・・・ (10)
となる。そして、更新割り当て範囲は、行列yの部分行列y(nn*(k−1):min(n,nn*k),1)となる。
ステップS504において、スレッドは、行列ベクトル積の演算結果を格納する領域y(js:je)=0.0d0を実行して当該領域をゼロクリアする。
ステップS505において、スレッドは、バリア同期をとって、他のスレッドが自身に割り当てられた演算割り当て範囲の処理を開始できる状態になるまで処理を停止する。
ステップS506において、スレッドは、行列ベクトル積の演算に使用する各種変数j、ncnt、nbase,nsおよびneに対して以下の処理を実行して初期化を行なう
。そして、スレッドは、以下に示す処理(ステップS507〜S519)を実行する。
j = js
ncnt = 1
nbase = nfcnz(js)−1
ns = nfcnz(js)
ne = nfcnz(je)−1
ステップS507において、スレッドは、行列ベクトル積の演算に使用する変数iに対して下記の処理を実行して初期化を行なう。
i = ns
ステップS508において、スレッドは、以降の演算(ステップS510又はS511)によって得る演算結果の更新割り当て範囲を担当するスレッド番号(以下、「インデックス」という)を以下の処理によって計算し、変数indexに代入する。また、当該演算に使用するxの要素を取り出して、変数xxに代入する。
ii = nrow(i)
index = (ii+nn−1)/nn
xx = x(ii)
ステップS509において、スレッドは、ステップS508で算出したindexとnothrdとを比較する。そして、一致する場合、スレッドはステップS510に処理を移行する。また、一致しない場合、スレッドはステップS511に処理を移行する。
ステップS510において、スレッドは、以下のベクトル積の演算を実行し、演算結果を格納する行列yの要素を更新する。
y(ii) = y(ii)+a(i)*xx
ステップS511において、スレッドは、以下のベクトル積の演算を実行し、演算結果を演算結果退避領域に格納する。すなわち、演算結果を配列wに格納するとともに、配列iwにチェインを追加して、配列iwの位置情報領域に終端(tail)を示す値0を格納し、同じくデータ領域にa(i)の行番号を格納する。
w(nbase+ncnt) = a(i)*xx
iw(1,nbase+ncnt) = 0
iw(2,nbase+ncnt) = ii
ステップS512において、スレッドは、配列nentry(1,index,nothrd)が0か否かを判別する。配列nentry(1,index,nothrd)が0の場合、スレッドは、処理をステップ613に移行する。また、配列nentry(1,index,nothrd)が0でない場合、スレッドは、配列nentry(1,index,nothrd)に既にチェインが追加されていると判断し、処理をステップS514に移行する。
ステップS513において、スレッドは、以下の処理を行なって配列nentry(1,index,nothrd)にチェインを登録する。
nentry(1,index,nothrd) = nbase+ncnt
ステップS514において、スレッドは、以下の処理を行なって配列nentry(1,index,nothrd)にチェインを登録する。
nptr = nentry(2,index,nothrd)
nentry(2,index,nothrd) = nbase*ncnt
iw(1,nptr) = nbase+ncnt
ステップS515において、スレッドは、以下の処理を行なって変数ncnt、iをインクリメントする。
ncnt = ncnt+1
i = i+1
ステップS516において、スレッドは、変数iと変数neとを比較する。そして、i>neの場合、スレッドは、ステップS517に処理を移行する。また、i≦eの場合、スレッドは、ステップS508に処理を移行する。そして、ステップS508〜S516の処理を繰り返し行なう。
ステップS517において、スレッドは、以下の処理を行なって変数jの値をインクリメントする。
j = j+1
ステップS518において、スレッドは、変数jと変数jeとを比較する。そして、j>jeの場合、スレッドは、ステップS519に処理を移行する。また、j≦jeの場合、スレッドは、ステップS507に処理を移行する。そして、ステップS507〜S518に処理を繰り返し行なう。
以上に示したステップS507〜S519の処理により、スレッドは、自身に割り当てられた演算割り当て範囲についての演算が完了する。
ステップS519において、スレッドは、バリア同期をとって、他のスレッドが自身に割り当てられた演算割り当て範囲の処理を完了するまで処理を停止する。
ステップS520において、スレッドは、変数iを以下の処理によって初期化する。
i = 1
ステップS521において、スレッドは、以下の処理を行なって自身のスレッド番号以外のスレッドのスレッド番号を取得し、変数nothrd_nxtに格納する。
nothrd_nxt = mod(nothrd−1+i,numthrd)+1
ステップS522において、スレッドは、配列nentry(1,nothrd,nothrd_nxt)が0か否かを判別する。配列nentry(1,nothrd,nothrd_nxt)が0の場合、スレッドは、他のスレッドが登録したチェインはないと判断し、ステップS526に処理を移行する。また、配列nentry(1,nothrd,nothrd_nxt)が0でない場合、スレッドは、他のスレッドが登録したチェインが存在すると判断し、ステップS523に処理を移行する。
ステップS523において、スレッドは、以下の処理を行なって配列nentry(1,nothrd,nothrd_nxt)に格納されている値を変数nptrに格納する。
nptr = nentry(1,nothrd,nothrd_nxt)
ステップS524において、スレッドは、変数nptrが0か否かを判別する。そして、変数nptrが0の場合、スレッドは、ステップS526に処理を移行する。また、変数nptrが0でない場合、スレッドは、ステップS525に処理を移行する。
ステップS525において、スレッドは、以下の処理を行なって、自身の更新割り当て範囲y(ii)について、他のスレッドの演算割り当て範囲の演算結果を更新する。そして、スレッドは、ステップS524に処理を移行する。
ii = iw(2,nptr)
y(ii) = y(ii)+w(nptr)
nptr = iw(1,nptr)
ステップS526において、スレッドは、以下の処理を行なって変数iをインクリメントする。
i = i+1
ステップS527において、スレッドは、変数iとnumthrd−1と比較する。そして、i>numthrd−1の場合、スレッドは、ステップS528に処理を移行する。また、i≦numthrd−1の場合、スレッドは、ステップS521に処理を移行する。そして、ステップS509〜S527の処理を繰り返す。
以上の処理によって、スレッドは、他のスレッドの演算割り当て範囲の演算結果を、自身の更新割り当て範囲に反映する処理が完了する。
ステップS528において、スレッドは、バリア同期をとって、他のスレッドの処理が完了するまで処理を停止する。そして、全スレッドの処理が完了すると、行列matのベクトル積の演算結果が変数y(1:n)に得られる(ステップS529)。
(第2の実施例)
第1の実施例では、2次元配列iwを行列のベクトル積演算に使用した場合について説明したが、例えば、配列iwには1次元配列を使用してもよい。以下、配列iwに1次元配列を使用した場合についての例を説明する。
図6は、本実施例に係る行列ベクトル積の演算の概要を説明する図である。なお、図3と同様に、図6に示す1次元配列w、iw、3次元配列nentryは、図2に示した行列matについて演算を行なう場合の例を示しているが、これに限定する趣旨でないのは当然である。
配列wは、図3と同様に、配列aに格納されている要素について、式(8)による演算結果を格納する1次元配列である。したがって、配列wは配列aと同じ大きさ(同じ構成)の1次元配列とすればよい。
配列iwは、配列wに格納されている要素について、式(8)による演算を行なった場合の要素ai,jが属する行番号(すなわち、nrow(i)に格納されている値)を格納する1次元配列である。当該行番号が格納される要素位置は、配列nrow(または配列a)と同じ要素位置に格納される。例えば、当該行番号は、配列nrow(i)と同じ要素位置iw(i)に格納される。
配列nentryは、図3と同様に、更新割り当て範囲毎に、演算割り当て範囲の演算結果w(i)に対応するiw(i)が格納されている先頭位置情報と終端位置情報を格納する。
本実施例では、図1に示したように更新割り当て範囲が2つ、演算割り当て範囲が2つなので、配列nentryは図3に示すように2×2の2次元配列となる。また、各要素は2つの要素で構成され、その1つの要素は先頭位置領域であり、もう1つの要素は終端位置領域である。本実施例では、両領域とも整数型として記憶領域を確保する。
例えば、式(2)に示した列ベクトルxが式(9)の場合について、行列matと列ベクトルxのベクトル積を考える。
この時、CPU#1は、演算割り当て範囲における式(9)の演算を実行する。そして、当該演算が更新割り当て範囲である場合には、演算結果を格納する配列yに演算結果を格納し、当該演算が更新割り当て範囲でない場合には、演算結果を配列wに格納する。
例えば、CPU#1は、演算結果「1」(=a(1)×x(1))、「−8」(=a(3)×x(2))を、それぞれ配列y(1)、y(2)に格納し、演算結果「2」(=a(2)×x(1))、「2」(=a(4)×x(2))を、それぞれ配列w(1)、w(2)に格納する。
ここで、CPU#1は、演算結果「2」(=a(2)×x(1))を配列w(1)に格納する時、新たなチェインのデータ領域iw(2)に、a(2)に対応するnrow(2)の値を格納する。
同様に、CPU#1は、演算結果「2」(=a(4)×x(2))を配列w(2)に格納する時、新たなチェインのデータ領域iw(4)に、a(4)に対応するnrow(4)の値を格納する。
CPU#2も同様の処理を行なう。
各CPUが自身に割り当てられた演算割り当て範囲について演算を完了すると、各CPUは、自身に割り当てられた更新割り当て範囲について、配列nentryを参照する。そして、当該nentryの先頭位置領域が示すチェインiwから、当該nentryの終端位置領域が示すチェインiwまで、たどりながらチェインiwのデータ領域を参照する。そして、各チェインiwに対応する配列wに格納されている演算結果が、演算結果を格納する配列yのいずれの要素に加算されるものかを判断し、当該配列yの要素に加算する。
例えば、CPU#1は、nentry(1,1,2)の先頭位置領域を参照する。そして、配列iwの5番目のデータを参照する。すると、行番号が第1行とわかるので、当該チェインに対応する演算結果w(5)は、y(1)に加算するものと判断し、y(1)の値に演算結果w(5)を加算した値をy(1)に格納する。以上の処理を、チェインの終端まで行なう。CPU#2についても同様である。
以上の処理によって、行列matと列ベクトルxとのベクトル積の演算結果を配列yに得ることができる。
図7A〜7Cは、本実施例に係る行列のベクトル積の演算処理の具体例を示すフローチャートである。図7A〜7Cに示すフローチャートは、n行n列のスパース行列matとn行1列の列ベクトルxとの演算処理を示す。
なお、以下の処理において、行列matの非ゼロ要素の総数をnz、並列実行するスレッドの数をnumthrdとする。また、行列matを圧縮列格納方式にしたがって非ゼロ要素を格納した1次元配列をa(nz)とする。また、配列a(nz)に格納した各要素の行番号を、当該要素を格納したa(nz)の配列番号と同じ配列番号の位置に格納する1次元配列をnrow(nz)とする。また、行列matの各列における最初の非ゼロ要素が格納されているa(nz)の位置を格納する1次元配列をnfcz(n)とする。
また、列ベクトルxを格納する1次元配列をx(n)、演算結果を格納する1次元配列をy(n)とする。そして、図3で説明した作業領域を1次元配列w(nz)、iw(nz)、3次元配列nentry(2,numthrd,numthrd)とする。
ステップS700において、演算装置100は、例えば、行列matと列ベクトルxが入力されると、行列matを圧縮列格納方式にしたがって配列aに格納する。そして、以下に示す行列のベクトル積演算mat*xを開始する。
ステップS701において、演算装置100は、並列処理を実行するスレッドをnumthrdだけ確保する。さらに、演算装置100は、配列nentry(2,numthrd,numthrd)の領域を共有メモリに確保する。そして、演算装置100は、nentry=0により当該ポインタをゼロクリアする。
ステップS702において、演算装置100は、ステップS701で確保したスレッド数numthrdのスレッドを生成する。そして、演算装置100は、各スレッドにスレッド番号nothrd(1〜numthrd)を割り当てる。
ステップS703において、スレッドは、行列matの次数nをnumthrdで均等に分割する。そして、各スレッドが分担する区分js〜jeを決定する。この時、スレッドは、次式によりjsおよびjeを算出し、各スレッドに対して、演算割り当て範囲と更新割り当て範囲を割り当てる。
nn = (n+numthrd−1)/numthrd
js = nn*(nothrd−1)
je = min(n,nn*nothrd)
ステップS704において、スレッドは、行列ベクトル積の演算結果を格納する領域y(js:je)=0.0d0により当該領域をゼロクリアする。
ステップS705において、スレッドは、バリア同期をとって、他のスレッドが自身に割り当てられた演算割り当て範囲の処理を開始できる状態になるまで処理を停止する。
ステップS706において、スレッドは、行列ベクトル積の演算に使用する各種変数j、ncnt、nsおよびneに対して以下の処理を実行して初期化を行なう。そして、スレッドは、以下に示す処理(ステップS707〜S719)を各スレッドに実行させる。
j = js
ncnt = 1
ns = nfcnz(js)
ne = nfcnz(je)−1
ステップS707において、スレッドは、行列ベクトル積の演算に使用する変数iに対して下記の処理を実行して初期化を行なう。
i = ns
ステップS708において、スレッドは、以降の演算(ステップS710又はS711)によって得る演算結果のインデックスを以下の処理によって計算し、変数indexに代入する。また、当該演算に使用する列ベクトルxの要素を取り出して、変数xxに代入する。
ii = nrow(i)
index = (ii+nn−1)/nn
xx = x(ii)
ステップS709において、スレッドは、ステップS708で算出したindexとnothrdとを比較する。そして、一致する場合、スレッドはステップS710に処理を移行する。また、一致しない場合、スレッドはステップS711に処理を移行する。
ステップS710において、スレッドは、以下のベクトル積の演算を実行し、演算結果を格納する行列yの要素を更新する。
y(ii) = y(ii)+a(i)*xx
ステップS711において、スレッドは、以下のベクトル積の演算を実行し、演算結果
を演算結果退避領域に格納する。すなわち、演算結果を配列wに格納するとともに、配列iwにチェインの終端(tail)を示す0を格納する。
w(i) = a(i)*xx
iw(i) = 0
ステップS712において、スレッドは、配列nentry(1,index,nothrd)が0か否かを判別する。配列nentry(1,index,nothrd)が0の場合、スレッドは、処理をステップ613に移行する。また、配列nentry(1,index,nothrd)が0でない場合、スレッドは、配列nentry(1,index,nothrd)に既にチェインが追加されていると判断し、処理をステップS714に移行する。
ステップS713において、スレッドは、以下の処理を行なって配列nentry(1,index,nothrd)にチェインを登録する。
nentry(1,index,nothrd) = i
ステップS714において、スレッドは、以下の処理を行なって配列nentry(1,index,nothrd)にチェインを登録する。
nptr = nentry(2,index,nothrd)
nentry(2,index,nothrd) = i
iw(nptr) = i
ステップS715において、スレッドは、以下の処理を行なって変数iをインクリメントする。
i = i+1
ステップS716において、スレッドは、変数iと変数neとを比較する。そして、i>neの場合、スレッドは、ステップS717に処理を移行する。また、i≦eの場合、スレッドは、ステップS708に処理を移行する。そして、ステップS708〜S716の処理を繰り返し行なう。
ステップS717において、スレッドは、以下の処理を行なって変数jの値をインクリメントする。
j = j+1
ステップS718において、スレッドは、変数jと変数jeとを比較する。そして、j>jnの場合、スレッドは、ステップS719に処理を移行する。また、j≦jeの場合、スレッドは、ステップS707に処理を移行する。そして、ステップS707〜S718に処理を繰り返し行なう。
以上に示したステップS707〜S719の処理により、スレッドは、自身に割り当てられた演算割り当て範囲についての演算が完了する。
ステップS719において、スレッドは、バリア同期をとって、他のスレッドが自身に割り当てられた演算割り当て範囲の処理を完了するまで処理を停止する。
ステップS720において、スレッドは、変数iを以下の処理によって初期化する。
i = 1
ステップS721において、スレッドは、以下の処理を行なって自身のスレッド番号以外のスレッドのスレッド番号を取得し、変数nothrd_nxtに格納する。
nothrd_nxt = mod(nothrd−1+i,numthrd)+1
ステップS722において、スレッドは、配列nentry(1,nothrd,no
thrd_nxt)が0か否かを判別する。配列nentry(1,nothrd,nothrd_nxt)が0の場合、スレッドは、他のスレッドが登録したチェインはないと判断し、ステップS726に処理を移行する。また、配列nentry(1,nothrd,nothrd_nxt)が0でない場合、スレッドは、他のスレッドが登録したチェインが存在すると判断し、ステップS723に処理を移行する。
ステップS723において、スレッドは、以下の処理を行なって配列nentry(1,nothrd,nothrd_nxt)に格納されている値を変数nptrに格納する。
nptr = nentry(1,nothrd,nothrd_nxt)
ステップS724において、スレッドは、変数nptrが0か否かを判別する。そして、変数nptrが0の場合、スレッドは、ステップS726に処理を移行する。また、変数nptrが0でない場合、スレッドは、ステップS725に処理を移行する。
ステップS725において、スレッドは、以下の処理を行なって、自身の更新割り当て範囲y(ii)について、他のスレッドの演算割り当て範囲の演算結果を更新する。そして、スレッドは、ステップS724に処理を移行する。
ii = nrow(nptr)
y(ii) = y(ii)+w(nptr)
nptr = iw(nptr)
ステップS726において、スレッドは、以下の処理を行なって変数iをインクリメントする。
i = i+1
ステップS727において、スレッドは、変数iとnumthrd−1と比較する。そして、i>numthrd−1の場合、スレッドは、ステップS728に処理を移行する。また、i≦numthrd−1の場合、スレッドは、ステップS721に処理を移行する。そして、ステップS709〜S727の処理を繰り返す。
以上の処理によって、スレッドは、他のスレッドの演算割り当て範囲の演算結果を、自身の更新割り当て範囲に反映する処理が完了する。
ステップS728において、スレッドは、バリア同期をとって、他のスレッドの処理が完了するまで処理を停止する。そして、全スレッドの処理が完了すると、行列matのベクトル積の演算結果が変数y(1:n)に得られる(ステップS829)。
図8は、本実施例に係る行列のベクトル積演算を実行する演算装置100の構成例を示す図である。
図8に示す演算装置100は、複数のメモリモジュール#1、#2、・・・、#nと、複数のCPU#1、#2、・・・、#nと、相互結合網901と、を少なくとも備える共有メモリ型演算装置である。
各メモリモジュール#1、#2、・・・、#nは、各CPU#1、#2、・・・、#nと、相互結合網901を介して接続されている。そして、例えば、本実施例に係るベクトル演算に使用する配列a、nfcnz、nrow、w,iw,nentry等の領域を提供する共有メモリとして使用される。
各CPU#1、#2、・・・、#nは、L2キャッシュおよびバスインタフェースと、L1キャッシュを有する2つのcpuコアと、を備える。そして、各cpuコアは、バス
インタフェースおよび相互結合網901を介して他のcpuコアやメモリモジュールとアクセス可能である。
なお、図8は、1つのCPUユニットにcpuコアが2ユニット搭載されている場合について示しているが、この構成に限定する趣旨ではないのは当然である。例えば、1つのCPUユニットにcpuコアが4ユニット搭載されていてもよい。
その他、図示しないが、演算装置100には、例えば、本実施例に係る行列のベクトル積演算を実行するプログラム等を記憶するために磁気ディスク装置等で構成される記憶装置も備えてもよい。
以上に説明したように、本実施例に係る行列のベクトル積の演算方法は、各スレッドに対して、別個に演算割り当て範囲と更新割り当て範囲を割り当てる。各スレッドは、並列的に自身に割り当てた演算割り当て範囲の演算を実施し、演算結果が更新割り当て範囲である場合には演算結果記憶領域に直接記憶し、演算結果が更新割り当て範囲でない場合には演算結果退避領域に記憶する。そして、全スレッドの演算処理終了後、各スレッドは、並列的に自身に割り当てられた更新割り当て範囲の更新処理を実施する。
したがって、各スレッドは、演算割り当て範囲における演算処理と、更新割り当て範囲における更新処理と、を並列に実行することが可能となる。その結果、行列のベクトル積を効率よく並列処理することが可能となる。
一般に、圧縮列格納法で格納されたスパース行列と列ベクトルとの積は、逐次プログラムを単純にOpenMP FortranのOCL(Object Constrain
Language)挿入などでは簡単に並列化することはできないが、本実施例に係る演算方法によれば、上述の理由から、簡単かつ効率的に並列化することが可能となる。
その結果、例えば、スパース行列の連立1次方程式を反復解法で解くときにも、行列のベクトル積を効率よく繰り返し計算することが可能となる。そのため、例えば、図8に示したSMP(Symmetric Multiple Processor)システムの演算装置を用いて圧縮列格納法で格納された行列のベクトル積を効率的かつ並列化して行なうことが可能となる。
また、行列のベクトル積を使う連立1次方程式で使用する反復法(例えば、BICGSTAB(L)法)などに本実施例に係る演算方法を使用することにより、ほぼ線形な台数効果を得ることができる。
さらに、複数のCPUで行列のベクトル積を並列に計算する場合、行方向に行を均等に分割したそれぞれの区間ごとの、区間に属する列に存在する非ゼロの対角要素からの距離に関する分布がほぼ同じ場合に、より高い並列処理による台数効果を得ることができる。十分に大きな問題の場合にも、ほぼ線形な台数効果を引き出すことができる。
以上の実施例1〜nを含む実施形態に関し、さらに以下の付記を開示する。
(付記1) 複数のスレッドを同時並列的に使用して行列と列ベクトルとの積を算出するプログラムであって、
前記行列を所定の範囲で分割して部分行列を生成し、該部分行列についての行列のベクトル積の演算処理を、前記スレッド毎に割り当てる演算割り当て範囲を決定する演算割り当て範囲決定処理と、
前記スレッドが算出した演算結果から、前記行列と列ベクトルとの積の一部を求める演算結果の更新処理を、前記スレッド毎に割り当てる更新割り当て範囲を決定する更新割り
当て範囲決定処理と、
前記演算割り当て範囲における前記部分行列を、前記行列を圧縮列格納法にしたがって圧縮して記憶する行列記憶手段から読み出し、該部分行列についての行列のベクトル積の演算処理を前記スレッドに実行させるベクトル演算処理と、
該演算結果が前記更新割り当て範囲か否かを判別し、前記更新割り当て範囲の場合には前記演算結果を、前記行列と列ベクトルとの積を記憶する演算結果記憶手段に記憶し、前記更新割り当て範囲でない場合には前記演算結果を、前記行列と前記列ベクトルとの積を一時的に記憶する演算結果退避手段に記憶させる演算結果振り分け処理と、
該演算結果退避手段から他のスレッドが算出した更新割り当て範囲の演算結果を読み出し、前記演算結果記憶手段に記憶されている演算結果を更新する演算結果更新処理と、
を演算装置に実行させるプログラム。
(付記2) 前記演算割り当て範囲決定処理は、前記行列の列を均等幅に分割して部分行列を生成する、
ことを特徴とする付記1に記載のプログラム。
(付記3) 前記更新割り当て範囲決定処理は、前記行列と前記列ベクトルとの積を格納する列ベクトルの列を均等幅に分割して部分列ベクトルを生成し、該部分列ベクトルの更新処理を、前記スレッド毎に割り当てる、
ことを特徴とする付記1に記載のプログラム。
(付記4) 前記行列記憶手段は、
前記行列の非ゼロ要素を列ごとに抽出して記憶する第1の配列と、
該第1の配列の各要素が属する前記行列における行番号を記憶する第2の配列と、
前記第1および第2の配列の要素位置であって前記行列の各列の先頭要素が格納される要素位置を記憶する第3の配列と、
を備えることを特徴とする付記1に記載のプログラム。
(付記5) 前記演算結果退避手段は、
前記更新割り当て範囲外の演算結果を記憶する第1の配列と、
該演算結果の記憶する順に対応して、該演算に使用した前記行列の要素の行番号を記憶する第2の配列と、
前記更新割り当て範囲毎に、該更新割り当て範囲の演算結果が記憶されている前記第2の配列の位置を記憶する第3の配列と、
を備えることを特徴とする付記1に記載のプログラム。
(付記6) 前記演算結果更新処理は、
前記第3の配列から、他のスレッドが算出した更新割り当て範囲の演算結果を得る演算に使用した前記行列の要素の行番号が記憶されている前記第2の配列の位置を取得し、該行番号に応じて、前記演算結果記憶手段に記憶されている更新すべき演算結果を特定する、
を備えることを特徴とする付記5に記載のプログラム。
(付記7) 前記第2の配列は、前記行番号を記憶する第1の要素と次の行番号が記憶されている要素の位置を記憶する第2の要素とを1つの単位とするチェイン構造を有する、
ことを特徴とする付記5に記載のプログラム。
(付記8) 前記第1の配列には、前記行列の非ゼロ要素を列ごとに抽出して記憶する配列の要素の位置と同じ位置に、該要素から算出される演算結果が格納され、前記第2の配列には、前記行列の非ゼロ要素を列ごとに抽出して記憶する配列の要素の位置と同じ位置に、該要素の演算に使用した前記行列の要素の行番号を記憶する、
ことを特徴とする付記5に記載のプログラム。
(付記9) 複数のスレッドを同時並列的に使用して行列と列ベクトルとの積を算出する演算方法であって、
前記行列を所定の範囲で分割して部分行列を生成し、該部分行列についての行列のベクトル積の演算処理を、前記スレッド毎に割り当てる演算割り当て範囲を決定する演算割り当て範囲決定処理と、
前記スレッドが算出した演算結果から、前記行列と列ベクトルとの積の一部を求める演算結果の更新処理を、前記スレッド毎に割り当てる更新割り当て範囲を決定する更新割り当て範囲決定処理と、
前記演算割り当て範囲における前記部分行列を、前記行列を圧縮列格納法にしたがって圧縮して記憶する行列記憶手段から読み出し、該部分行列についての行列のベクトル積の演算処理を前記スレッドに実行させるベクトル演算処理と、
該演算結果が前記更新割り当て範囲か否かを判別し、前記更新割り当て範囲の場合には前記演算結果を、前記行列と列ベクトルとの積を記憶する演算結果記憶手段に記憶し、前記更新割り当て範囲でない場合には前記演算結果を、前記行列と前記列ベクトルとの積を一時的に記憶する演算結果退避手段に記憶させる演算結果振り分け処理と、
該演算結果退避手段から他のスレッドが算出した更新割り当て範囲の演算結果を読み出し、前記演算結果記憶手段に記憶されている演算結果を更新する演算結果更新処理と、
を演算装置に実行させる方法。
(付記10) 複数のスレッドを同時並列的に使用して行列と列ベクトルとの積を算出する演算装置であって、
前記行列を圧縮列格納法にしたがって圧縮して記憶する行列記憶手段と、
前記行列と前記列ベクトルとの積を一時的に記憶する演算結果退避手段と、
前記行列を所定の範囲で分割して部分行列を生成し、該部分行列についての行列のベクトル積の演算処理を、前記スレッド毎に割り当てる演算割り当て範囲を決定する演算割り当て範囲決定手段と、
前記スレッドが算出した演算結果から、前記行列と列ベクトルとの積の一部を求める演算結果の更新処理を、前記スレッド毎に割り当てる更新割り当て範囲を決定する更新割り当て範囲決定手段と、
前記演算割り当て範囲における前記部分行列を前記行列記憶手段から読み出し、該部分行列についての行列のベクトル積の演算処理を前記スレッドに実行させるベクトル演算処理手段と、
該演算結果が前記更新割り当て範囲か否かを判別し、前記更新割り当て範囲の場合には前記演算結果を、前記行列と列ベクトルとの積を記憶する演算結果記憶手段に記憶し、前記更新割り当て範囲でない場合には前記演算結果を、前記演算結果退避手段に記憶させる演算結果振り分け手段と、
該演算結果退避手段から他のスレッドが算出した更新割り当て範囲の演算結果を読み出し、前記演算結果記憶手段に記憶されている演算結果を更新する演算結果更新手段と、
を備える演算装置。
本実施例に係る演算割り当て範囲および更新割り当て範囲を説明する図である。 本実施例に係る圧縮列格納法の説明をする図である。 第1の実施例に係る行列ベクトル積の演算の概要を説明する図である。 第1の実施例に係る行列のベクトル積の演算の処理を示すフローチャートである。 第1の実施例に係る行列のベクトル積の演算処理の具体例を示すフローチャートである。 第1の実施例に係る行列のベクトル積の演算処理の具体例を示すフローチャートである。 第1の実施例に係る行列のベクトル積の演算処理の具体例を示すフローチャートである。 第2の実施例に係る行列ベクトル積の演算の概要を説明する図である。 第2の実施例に係る行列のベクトル積の演算処理の具体例を示すフローチャートである。 第2の実施例に係る行列のベクトル積の演算処理の具体例を示すフローチャートである。 第2の実施例に係る行列のベクトル積の演算処理の具体例を示すフローチャートである。 本実施例に係る行列のベクトル積演算を実行する演算装置100の構成例を示す図である。

Claims (5)

  1. 複数のスレッドを同時並列的に使用して行列と列ベクトルとの積を算出するプログラムであって、
    前記行列を所定の範囲で分割して部分行列を生成し、該部分行列についての行列のベクトル積の演算処理を、前記スレッド毎に割り当てる演算割り当て範囲を決定する演算割り当て範囲決定処理と、
    前記スレッドが算出した演算結果から、前記行列と列ベクトルとの積の一部を求める演算結果の更新処理を、前記スレッド毎に割り当てる更新割り当て範囲を決定する更新割り当て範囲決定処理と、
    前記演算割り当て範囲における前記部分行列を、前記行列を圧縮列格納法にしたがって圧縮して記憶する行列記憶手段から読み出し、該部分行列についての行列のベクトル積の演算処理を前記スレッドに実行させるベクトル演算処理と、
    該演算結果が前記更新割り当て範囲か否かを判別し、前記更新割り当て範囲の場合には前記演算結果を、前記行列と列ベクトルとの積を記憶する演算結果記憶手段に記憶し、前記更新割り当て範囲でない場合には前記演算結果を、前記行列と前記列ベクトルとの積を一時的に記憶する演算結果退避手段に記憶させる演算結果振り分け処理と、
    該演算結果退避手段から他のスレッドが算出した更新割り当て範囲の演算結果を読み出し、前記演算結果記憶手段に記憶されている演算結果を更新する演算結果更新処理と、
    を演算装置に実行させるプログラム。
  2. 前記行列記憶手段は、
    前記行列の非ゼロ要素を列ごとに抽出して記憶する第1の配列と、
    該第1の配列の各要素が属する前記行列における行番号を記憶する第2の配列と、
    前記第1および第2の配列の要素位置であって前記行列の各列の先頭要素が格納される要素位置を記憶する第3の配列と、
    を備えることを特徴とする請求項1に記載のプログラム。
  3. 前記演算結果退避手段は、
    前記更新割り当て範囲外の演算結果を記憶する第1の配列と、
    該演算結果の記憶する順に対応して、該演算に使用した前記行列の要素の行番号を記憶する第2の配列と、
    前記更新割り当て範囲毎に、該更新割り当て範囲の演算結果が記憶されている前記第2の配列の位置を記憶する第3の配列と、
    を備えることを特徴とする請求項1に記載のプログラム。
  4. 複数のスレッドを同時並列的に使用して行列と列ベクトルとの積を算出する演算方法であって、
    前記行列を所定の範囲で分割して部分行列を生成し、該部分行列についての行列のベクトル積の演算処理を、前記スレッド毎に割り当てる演算割り当て範囲を決定する演算割り当て範囲決定処理と、
    前記スレッドが算出した演算結果から、前記行列と列ベクトルとの積の一部を求める演算結果の更新処理を、前記スレッド毎に割り当てる更新割り当て範囲を決定する更新割り当て範囲決定処理と、
    前記演算割り当て範囲における前記部分行列を、前記行列を圧縮列格納法にしたがって圧縮して記憶する行列記憶手段から読み出し、該部分行列についての行列のベクトル積の演算処理を前記スレッドに実行させるベクトル演算処理と、
    該演算結果が前記更新割り当て範囲か否かを判別し、前記更新割り当て範囲の場合には前記演算結果を、前記行列と列ベクトルとの積を記憶する演算結果記憶手段に記憶し、前記更新割り当て範囲でない場合には前記演算結果を、前記行列と前記列ベクトルとの積を
    一時的に記憶する演算結果退避手段に記憶させる演算結果振り分け処理と、
    該演算結果退避手段から他のスレッドが算出した更新割り当て範囲の演算結果を読み出し、前記演算結果記憶手段に記憶されている演算結果を更新する演算結果更新処理と、
    を演算装置に実行させる方法。
  5. 複数のスレッドを同時並列的に使用して行列と列ベクトルとの積を算出する演算装置であって、
    前記行列を圧縮列格納法にしたがって圧縮して記憶する行列記憶手段と、
    前記行列と前記列ベクトルとの積を一時的に記憶する演算結果退避手段と、
    前記行列を所定の範囲で分割して部分行列を生成し、該部分行列についての行列のベクトル積の演算処理を、前記スレッド毎に割り当てる演算割り当て範囲を決定する演算割り当て範囲決定手段と、
    前記スレッドが算出した演算結果から、前記行列と列ベクトルとの積の一部を求める演算結果の更新処理を、前記スレッド毎に割り当てる更新割り当て範囲を決定する更新割り当て範囲決定手段と、
    前記演算割り当て範囲における前記部分行列を前記行列記憶手段から読み出し、該部分行列についての行列のベクトル積の演算処理を前記スレッドに実行させるベクトル演算処理手段と、
    該演算結果が前記更新割り当て範囲か否かを判別し、前記更新割り当て範囲の場合には前記演算結果を、前記行列と列ベクトルとの積を記憶する演算結果記憶手段に記憶し、前記更新割り当て範囲でない場合には前記演算結果を、前記演算結果退避手段に記憶させる演算結果振り分け手段と、
    該演算結果退避手段から他のスレッドが算出した更新割り当て範囲の演算結果を読み出し、前記演算結果記憶手段に記憶されている演算結果を更新する演算結果更新手段と、
    を備える演算装置。
JP2008041498A 2008-02-22 2008-02-22 ベクトル積の並列処理方法 Active JP5262177B2 (ja)

Priority Applications (1)

Application Number Priority Date Filing Date Title
JP2008041498A JP5262177B2 (ja) 2008-02-22 2008-02-22 ベクトル積の並列処理方法

Applications Claiming Priority (1)

Application Number Priority Date Filing Date Title
JP2008041498A JP5262177B2 (ja) 2008-02-22 2008-02-22 ベクトル積の並列処理方法

Publications (2)

Publication Number Publication Date
JP2009199430A true JP2009199430A (ja) 2009-09-03
JP5262177B2 JP5262177B2 (ja) 2013-08-14

Family

ID=41142844

Family Applications (1)

Application Number Title Priority Date Filing Date
JP2008041498A Active JP5262177B2 (ja) 2008-02-22 2008-02-22 ベクトル積の並列処理方法

Country Status (1)

Country Link
JP (1) JP5262177B2 (ja)

Cited By (3)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
GB2489526A (en) * 2011-04-01 2012-10-03 Schlumberger Holdings Representing and calculating with sparse matrixes in simulating incompressible fluid flows.
US9418048B2 (en) 2013-03-29 2016-08-16 Fujitsu Limited Apparatus and method for allocating shared storage areas to parallel processors for multiplication of sparse matrix and vector
CN112260695A (zh) * 2020-10-15 2021-01-22 苏州浪潮智能科技有限公司 压缩感知信号的重构方法、装置、fpga及存储介质

Families Citing this family (1)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
CN104572587B (zh) * 2014-12-23 2017-11-14 中国电子科技集团公司第三十八研究所 数据矩阵相乘的加速运算方法和装置

Citations (4)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
JPH02266458A (ja) * 1989-04-06 1990-10-31 Nec Corp ニューラルネットワークシミュレーション装置
JPH06175986A (ja) * 1992-12-10 1994-06-24 Nippon Telegr & Teleph Corp <Ntt> 行列演算の並列処理方法
JPH09212483A (ja) * 1996-01-31 1997-08-15 Fujitsu Ltd 多様な行列格納法を使用可能な連立方程式の並列処理装置および方法
JP2001209631A (ja) * 2000-01-25 2001-08-03 Nec Corp 行列ベクトル積演算システム及びそれに用いる行列格納システム並びにそれらの方法

Patent Citations (4)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
JPH02266458A (ja) * 1989-04-06 1990-10-31 Nec Corp ニューラルネットワークシミュレーション装置
JPH06175986A (ja) * 1992-12-10 1994-06-24 Nippon Telegr & Teleph Corp <Ntt> 行列演算の並列処理方法
JPH09212483A (ja) * 1996-01-31 1997-08-15 Fujitsu Ltd 多様な行列格納法を使用可能な連立方程式の並列処理装置および方法
JP2001209631A (ja) * 2000-01-25 2001-08-03 Nec Corp 行列ベクトル積演算システム及びそれに用いる行列格納システム並びにそれらの方法

Cited By (5)

* Cited by examiner, † Cited by third party
Publication number Priority date Publication date Assignee Title
GB2489526A (en) * 2011-04-01 2012-10-03 Schlumberger Holdings Representing and calculating with sparse matrixes in simulating incompressible fluid flows.
US9146902B2 (en) 2011-04-01 2015-09-29 Paul Frederick Cilgrim Dickenson Parallel computation of matrix problems
US9418048B2 (en) 2013-03-29 2016-08-16 Fujitsu Limited Apparatus and method for allocating shared storage areas to parallel processors for multiplication of sparse matrix and vector
CN112260695A (zh) * 2020-10-15 2021-01-22 苏州浪潮智能科技有限公司 压缩感知信号的重构方法、装置、fpga及存储介质
CN112260695B (zh) * 2020-10-15 2022-05-13 苏州浪潮智能科技有限公司 压缩感知信号的重构方法、装置、fpga及存储介质

Also Published As

Publication number Publication date
JP5262177B2 (ja) 2013-08-14

Similar Documents

Publication Publication Date Title
JP6977239B2 (ja) 行列乗算器
JP7329533B2 (ja) 演算を加速するための方法および加速器装置
EP3557425B1 (en) Accelerator and system for accelerating operations
CN108388537B (zh) 一种卷积神经网络加速装置和方法
US10768894B2 (en) Processor, information processing apparatus and operation method for processor
KR20190019081A (ko) 심층 신경망용 가속기
CN112106078A (zh) 神经网络处理元件
JP7453244B2 (ja) 推定装置、訓練装置、推定方法及びモデル生成方法
JP5374878B2 (ja) ハーネス配線経路算出方法、ハーネス配線経路設計支援装置及びプログラム
JP5262177B2 (ja) ベクトル積の並列処理方法
US10120717B2 (en) Method for optimizing the size of a data subset of a processing space for improved execution performance
CN109840585B (zh) 一种面向稀疏二维卷积的运算方法和系统
CN109416755B (zh) 人工智能并行处理方法、装置、可读存储介质、及终端
CN114995782B (zh) 数据处理方法、装置、设备和可读存储介质
CN110837483B (zh) 张量维度变换的方法以及装置
CN113254391A (zh) 一种神经网络加速器卷积计算和数据载入并行方法及装置
CN113485750B (zh) 数据处理方法及数据处理装置
CN117435855B (zh) 用于进行卷积运算的方法、电子设备和存储介质
CN114003201A (zh) 矩阵变换方法、装置及卷积神经网络加速器
JP5777458B2 (ja) パターン識別装置、パターン識別方法及びプログラム
JP2002163247A (ja) 共有メモリ型スカラ並列計算機における多次元フーリエ変換の並列処理方法
CN116541680A (zh) 基于轻量化时间序列缩减的工业设备状态预测方法与装置
Löhner Cache‐efficient renumbering for vectorization
JP6666548B2 (ja) 並列計算機、fft演算プログラムおよびfft演算方法
CN111191774A (zh) 面向精简卷积神经网络的低代价加速器架构及其处理方法

Legal Events

Date Code Title Description
A621 Written request for application examination

Free format text: JAPANESE INTERMEDIATE CODE: A621

Effective date: 20100917

A977 Report on retrieval

Free format text: JAPANESE INTERMEDIATE CODE: A971007

Effective date: 20121227

A131 Notification of reasons for refusal

Free format text: JAPANESE INTERMEDIATE CODE: A131

Effective date: 20130108

A521 Written amendment

Free format text: JAPANESE INTERMEDIATE CODE: A523

Effective date: 20130311

TRDD Decision of grant or rejection written
A01 Written decision to grant a patent or to grant a registration (utility model)

Free format text: JAPANESE INTERMEDIATE CODE: A01

Effective date: 20130402

A61 First payment of annual fees (during grant procedure)

Free format text: JAPANESE INTERMEDIATE CODE: A61

Effective date: 20130415

R150 Certificate of patent or registration of utility model

Free format text: JAPANESE INTERMEDIATE CODE: R150

Ref document number: 5262177

Country of ref document: JP

Free format text: JAPANESE INTERMEDIATE CODE: R150