2017-07-25 5 views
0

私はすでにを知っているEigen :: SparseMatrixのスパースパターンを設定する必要があります(私は一意のソートされた列インデックスと行オフセットを持っています)。明らかにそれはsetFromTripletsを介して可能だが、残念ながらsetFromTripletsは(少なくとも私の場合)メモリオーバーヘッドなしでEigen :: SparseMatrixのスパースパターンを設定する

を追加大量のメモリを必要と私はラインの間(この例では、ピーク時26Gbについて何かを消費小さな例に私の場合は

const long nRows = 5000000; 
const long nCols = 100000; 
const long nCols2Skip = 1000; 
//It's quite big! 
const long nTriplets2Reserve = nRows * (nCols/nCols2Skip) * 1.1; 
Eigen::SparseMatrix<double, Eigen::RowMajor, long> mat(nRows, nCols); 

std::vector<Eigen::Triplet<double, long>> triplets; 

triplets.reserve(nTriplets2Reserve); 
for(long row = 0; row < nRows; ++row){ 
    for(long col = 0; col < nCols; col += nCols2Skip){ 
     triplets.push_back(Eigen::Triplet<double, long>(row, col, 1)); 
    } 
} 
std::cout << "filling mat" << std::endl << std::flush; 
mat.setFromTriplets(triplets.begin(), triplets.end()); 

std::cout << "Finished! nnz " << mat.nonZeros() << std::endl; 
//Stupid way to check memory consumption 
std::cin.get(); 

を書きました結局、 "マット"と "フィニッシュ")と18Gb。 (私はhtopですべての小切手を作った)。 〜8Gbのオーバヘッドはかなり大きいです(私の "現実世界"の仕事では私はより大きなオーバーヘッドを持っています)。

だから、私は2つの質問があります。setFromTripletsは非常に多くのメモリを必要とする理由

  • できるだけ少ないオーバーヘッドで固有のスパースパターン::疎行列を埋めるためにどのように

    1. を?

    私の例が間違っている場合は教えてください。

    私の固有のバージョンは、私の英語

    EDITのため申し訳ありません3.3.2

    PSです:各トリプレットを手動でより速く動作し、ピーク時より少ないメモリを必要とinsertingpreallocation付き)みたいだ が見えます。しかし、私はまだそれがスパースパターンを設定することが可能であるかを知りたい手動

  • 答えて

    1

    広告1:あなたは内の要素を挿入することを保証できる場合は、内部関数startVecinsertBackを、使用してinsert無地よりも、もう少し効率的な場合があります字句的順序。

    広告2:setFromTripletsを使用する場合は、行列の転置バージョンに最初に要素が挿入されるため、行列のサイズの約2倍のサイズ(トリプレットコンテナのサイズ)が必要になります。すべての内部ベクトルがソートされていることを確認するための最終行列。先ほどの行列の構造を知っているなら、これは明らかにメモリの無駄ですが、任意の入力データを処理することを意図しています。

    例では、5000000 * 100000/1000 = 5e8の要素があります。 Tripletは、8 + 8 + 8 = 24バイト(vectorの場合は約12Gb)を必要とし、スパース行列の各要素は8 + 8 = 16バイト(値の場合はdouble、内側インデックスの場合はlong)マトリックスあたり約8Gbなので、合計で約28Gbが必要です。これは約26Gibです。

    ボーナス: あなたの行列は、より効率的に保存することができ、いくつかの特殊な構造を持っている、とあなたは固有の内部に深く掘るために喜んでいる場合は、「あなたもEigen::SparseBase<>から継承する新しいタイプを実装することも検討して(私はドンメモリ/パフォーマンスがあなたにとって非常に重要でない限り、これを記録する必要はなく、あなたは "まばらに"書かれた内部Eigenコードをたくさん読んでいきます...)。しかし、その場合は、マトリックスで何をしようとしているのか考えて、そのための特別な操作しか実装しない方が簡単でしょう。

    関連する問題