web-dev-qa-db-ja.com

スパース行列を格納するための形式

スパース行列を格納するために、COO、CSR、DIA、ELL、HYBなどの一般的な複数の形式があることを知っています(一部のストレージ形式へのリンク)が、これらのいずれにもゼロ以外の数が格納されていることはわかりません行ごと。

行ポインタの代わりに、行ごとの非ゼロエントリの数が格納されることを除いて、CSRと同様のスパース行列格納形式を作成することを検討しています。この情報があれば、アルゴリズムを高速化できます。行ポインタではなく、データセットが行ごとに非ゼロの数を期待するのは公平なことなのでしょうか。

自分自身は見つかりませんでしたが、この例はありませんか?

基本的に、新しいスパース行列ストレージ形式を作成したいのですが、この形式に何か問題があるのでしょうか。

2
Veridian

これは、CSRマトリックスを行ごとに前方にトラバースするときに、インデックスを累積し続けるだけで問題なく機能するはずです。追加のカウンター変数が必要になります。これは、ほとんどのプロセッサーが簡単に対応できるはずです。内側のループにメモリ参照を追加することすらありません。

これは、密なベクトル乗算による一般的なスパース行列の内部ループです。

for (i = 0; i < N; i++)
{  
    for (k = RowPtr[i]; k < RowPtr[i+1]; k++)
    {  
        result[i] += Val[k]*d[Col[k]];
    }  
}  

これは次のように変わります。

k = Count[0];
for (i = 0; i < N; i++)
{ 
    for (count = Count[i+1]; --count >= 0; k++)
    {  
        result[i] += Val[k]*d[Col[k]];
    }  
}  

私は2つの欠点を考えることができます:

  1. 一部のアルゴリズムで深刻なランダムアクセスが必要な場合は、使用する一時的なRowPtr配列を作成することをお勧めします。 (もちろん、これらのアルゴリズムはキャッシュに対応していないため、回避しようとしています。)
  2. 非標準の形式として、ライブラリ( Eigen など)を使用する機能が制限される場合がありますが、必要に応じて変換できる場合もあります。
1
Erik Eidt

CSR形式:

CSR形式 は、アイテムをすばやく見つけるために行ポインターを使用します。アイテム[i、j]を見つけるには、次のものが必要です。

  • 行「ポインター」を取得するための1つのインデックス付きアクセス(実際、配列AIでは行オフセット)
  • 一致する列を見つけるための(配列AJ内の)列インデックスへの最大n個のインデックス付きアクセス
  • アイテムがゼロでない場合に、アイテム(配列A内)を取得するための1つのインデックス付きアクセス。

何らかの理由で行iのゼロ以外の値の数に関心がある場合は、A [i] -A [i-1](またはA [i + 1] -A [ i] iを1から始める場合)。

問題は、マトリックスに新しいゼロ以外の値を設定する場合です。挿入する行の後にすべての行の「ポインター」をインクリメントする必要があり、列のインデックスと値を挿入する必要があります(これは、来る項目を移動することを意味します)その後)。

新しいフォーマット

行「ポインター」の代わりに、各行のゼロ以外の項目の数を追跡するつもりです。これは完全に実行可能です。Aを別の方法で解釈するだけです。

欠点は、行iの項目にアクセスすると、毎回、0とi-1の間のnのすべてのA [n]を合計する必要があることです。したがって、多くの追加を行う必要があります。要素にアクセスするたび。これはCSRよりもはるかに効率が悪くなります。

1
Christophe