私は現在、管理しているシミュレーションツール用に、C++のスパース行列/数学/反復ソルバーライブラリに取り組んでいます。既存のパッケージを使用したかったのですが、徹底的な調査の結果、シミュレーターに適したものは見つかりませんでした(flens、it ++、PetSC、eigenなどを調べました)。良いニュースは、私のソルバーとスパース行列構造が非常に効率的で堅牢になったことです。悪いニュースは、OpenMPを使用した並列化を検討していることです。学習曲線は、少し急です。
私たちが解決するドメインは、ブロック対角形式でまとめられたサブドメインに分割できます。したがって、私たちのストレージスキームは、それぞれがサブドメインに適した形式(たとえば、圧縮行ストレージ:CRS、圧縮対角ストレージ:CDS、高密度など)を持つ小さな正方行列(blocks [])の配列のように見えます。サブドメイン間の接続を説明するバックグラウンドマトリックス(現在CRSを使用)。
ほとんどの(すべて?)反復ソルバーの「ホットスポット」は、行列ベクトルの乗算演算です。これは、私のライブラリにも当てはまります。したがって、私はMxVルーチンの最適化に注力してきました。ブロック対角構造の場合、M * x=bの擬似コードは次のようになります。
b=background_matrix*x
start_index = 1;
end_index = 0;
for(i=1:number of blocks) {
end_index=start_index+blocks[i].numRows();
b.range(start_index, end_index) += blocks[i] * x.range(start_index, end_index);
start_index = end_index+1;
}
ここで、background_matrixはバックグラウンド(CRS)行列、blocksはサブドメイン行列の配列、.rangeは開始インデックスから終了インデックスまでのベクトルの部分を返します。
操作はループの他の反復から独立しているため、明らかにループを並列化できます(そして並列化できます)(範囲は重複しません)。通常のシステムには10〜15個のブロックがあるため、4つ以上のスレッドが実際に大きな違いを生みます。
並列化が適切なオプションであると見なされているもう1つの場所は、各サブドメインストレージスキームのMxV操作です(上記のコードの1行目と6行目で呼び出します)。CRS、CDS、および密行列MxV操作の並列化についてはたくさんあります。通常、2つのスレッドで素晴らしいブーストが見られ、スレッドが追加されるにつれて収穫逓減が大幅に減少します。
上記のコードのブロックループで4つのスレッドが使用され、それらの各スレッドがサブドメインの解決に2つのスレッドを使用するスキームを想定しています。ただし、OpenMPを使用してスレッドのプールを管理する方法がわかりません。openmpforループのスレッド数を制限することは可能ですか?このマルチレベルの並列処理は、実際には意味のあることですか?私がここで提案したことについての他の考えはありがたいです(そして最後まで読んでくれてありがとう!)