2013-08-09 2 views
5

私は、複数の(ソフト)制約を持つ疎線形システムを構築しています。私はboost :: ublasを使って行列を構築していたいくつかのコードをEigenに変換しています。 boost:ublasは、既知の(または推定された)非ゼロの数を持つ疎行列を作成する便利な方法を持ち、その要素を更新するのにかなり高速の演算子(int row、int col)を持ちます。EigenのSparseMatrix構造

  • を疎行列:: setFromTripletsを使用して::
    私のシステムは多くの制約があり、次のように

    問題があります。素朴で、やや誇張された例として、500 nnzで10億の冗長制約(つまり、非ゼロのcoeffが10億回変更されている)を持つ100x100の疎な行列があるとしましょう。 setFromTripletsは10億の係数を格納する必要があります。その大部分は、500個の非ゼロ係数のセットを形成するために合計されます。それは本当に効率的でもメモリに優しいものでもありません。 もちろん、私はstd :: vectorをstd :: mapで置き換えることができますが、手動で制約を累積することはできますが、これは何とか疎な行列クラスを持っていて、それも効率的ではありません。

  • SparseMatrix :: insert(i、j、val)の使用:
    要素が既に存在する場合は機能しません。私の問題は、すでに存在する係数を累積することができることです。

  • SparseMatrix :: coeffRef(i、j)を使用して:
    これは機能し、私が探している機能になります。しかし、boost :: ubasよりも数桁遅いです。私はそれのためのより良い機能を見ていないことに驚いています。 これは、あらかじめわかっていない非ゼロの数に起因すると考えられ、複数の再割り当てが強制されます(これは実際には起こります)。ただし、SparseMatrix :: reserve()を使用すると、圧縮された行列に対してのみ機能するため、効果はありません(ソース内のコメントには、「アサーションの前に非圧縮モードではこの関数は意味がありません」と記載されています)。ドキュメントが言うように...と、「疎行列に新しい要素の挿入が、これは非圧縮モードへの以降の変換」。

    はまだありながら固有で疎行列を構築するための最も効率的な方法は何である

その係数更新することができ、複数回

おかげ

[EDIT:サンプル使用事例:10非ZERを有する10×10マトリックスos。簡単にするために、マトリックスは、=>が動作

SparseMatrix<double> mat(10, 10); 
for (int i=0; i<10; i++) { 
    for (int j=0; j<1000000; j++) { 
    mat.coeffRef(i, i) += rand()%10; 
    } 
} 

]対角線が、(より大きな行列もちろん、より現実的な設定のため)ublasオペレータより遅い桁()です。

std::vector<Eigen::Triplet<double> > triplets(10000000); 
int k=0; 
for (int i=0; i<10; i++) { 
    for (int j=0; j<1000000; j++) { 
    triplets[k++] = Eigen::Triplet<double>(i,i,rand()%10); 
    } 
} 
SparseMatrix<double> mat(10, 10); 
mat.setFromTriplets(triplets.begin(), triplets.end()); 

=>ないメモリ優しい... coeffRef効率的なのinsertを作るために

+0

私はあなたの問題にかなり従っていません。ユースケースの簡略化されたバージョンを投稿しますか?理想的には、10x10スパース行列、たとえば10以外のゼロ行列でそれを行います。 – Escualo

+0

私はほんの一例を追加しました。 – WhitAngl

+0

あなたの例は意味を持ちません。私はあなたの実際のユースケースとして私の質問を意味した。つまり、あなたは疎な行列を持っています。そしてそれで何かをしてから、何をしますか?あなたは行列を変えますか?係数をシャッフルしますか?新しい係数セットを追加しますか? – Escualo

答えて

5

、あなたはnnzは、各列の非ゼロの推定数を含むあるmat.reserve(nnz)を使用して十分なスペースを確保する必要があります。多数の再割り当て/コピーを避けるために、これらの数値をわずかに過大評価するほうがよい。もう1つの相補的なやり方は、最初に要素(i,j)にアクセスするときに、この要素が列jの最後の要素であることを確認することです。

スパース性パターンを簡単に計算できるのであれば、値に0のユニークなトリプレットのベクトルを入力し、coeffRefが高速になります。

+0

ありがとう!私はcoeffRefが行列を非圧縮にしたと考えました。「新しい要素をSparseMatrixに挿入すると、後でこれが非圧縮モードに変換されます」と予約関数は、非圧縮行列(これは、なぜか分からない)ありがとう! – WhitAngl

+0

圧縮モードの場合はsize_tをとり、非圧縮モードの場合はベクトル式を取る2つの予約署名があります。 – ggael

関連する問題