2016-12-20 29 views
0

親愛なるStackOverflowのコミュニティ:BOOST疎行列

私はかなり後押しする新たなんだ、と私はそのuBLASライブラリのスパース行列を使用しようとしています。私が遭遇する問題の1つは、疎な行列を計算した後、それをバイナリファイルに保存し、他のいくつかのプログラムからファイルを読み込み、疎行列を復元することです。私はBOOST疎行列のために同様の書き込み操作を行うことができます場合、私は思ったんだけど

std::ofstream ofsDat("file.dat", std::ofstream::out); 
ofsDat.write((char*)A, sizeof(float)*100); 
ofsDat.close(); 

:通常、私には、以下の方法(たとえば、私は100台のフロートを持つ配列Aを持っている場合)のファイルを書くのか?もしそうなら、ofstream :: writeの第2引数は何でしょうか? (データチャンクのサイズである必要があります)

答えて

0

ブーストスパース行列は、ゼロ以外の値しか格納しません。行列の密な表現には&Aはありません。バイナリ出力が必要な場合は、その場で自分で構築する必要があります。 ios::outが必要なわけではありません。

std::ofstream test("./file.dat", std::ios::binary); 

またはofstreamは文字ストリームとして扱うことで出力を変更することができます。次に:

#include <iostream> 
#include <fstream> 
#include <boost/numeric/ublas/matrix_sparse.hpp> 
#include <boost/numeric/ublas/storage.hpp> 

namespace ublas = boost::numeric::ublas; 

int main() 
{ 
    size_t width= 10; 
    size_t depth= 10; 
    ublas::compressed_matrix<double> m(width, depth); 
    m(0, 0) = 9; 
    m(1, 0) = 2; 
    m(0, 1) = 3; 
    m(5, 5) = 7; 

    std::ofstream test("./file.dat", std::ios::binary); 
    double zero= 0.0; 
    for(int i=0; i < width; ++i) 
     for (int j=0; j< depth; ++j) 
     { 
      double* temp= m.find_element(i, j); 
      if(temp) 
       test.write((char*)temp, sizeof(double)); 
      else 
       test.write((char*)&zero, sizeof(double)); 
     } 
    test.close(); 
} 

さらに詳しい情報をファイルに書き込むことなく、マトリックスは既知の幅と深さでなければなりません。私は実際に相手側の入力を調べ、テキストファイルではできないかどうかを確認します。次に、あなただけにしている:

test << m; 
+0

お返事ありがとうございました!私はすでに、この "読み書き"がメモリのチャンクを直接管理する方法で行うことができると私の古い考え方を諦めました。だから、私は「要素ごとに読み書きする」ことを考えていました。あなたの例はまさにこれを行います。私の唯一の懸念は、M個の非ゼロを持つ疎次元行列(NxN)の場合、2つのループを実行する複雑さはN^2ですが、この書き込み操作は実際には非ゼロ要素へのMアクセスを必要とします。それで、すべての非ゼロ要素を効率的に反復する方法はありますか? – YangLou

+0

私はこのリンクを見つけました[リンク](http://stackoverflow.com/questions/1795658/looping-over-the-non-zero-elements-of-a-ublas-sparse-matrix)すべての非ゼロを通過するために、すべての要素(非ゼロとゼロ)を反復処理するには?または私はここに何かを逃していますか? – YangLou

+0

こんにちは@ヤングロー。私はプロファイラで確認していないが、私の推測では、ファイルを書いてゼロを埋めるので、データを得ることはボトルネックにとってあまり重要ではないということです。私は速く、疎な行列で、行列の計算に適用可能であると信じています。 – lakeweb

0

最後にいくつかの検索や裁判の後、私はこの書き込みを行う方法を発見し、スパース行列を読み込みます。私の仕事は実際には比較的簡単なので、より複雑でより一般的な目的のために、この粗い方法がうまくいくかどうかわかりません。

基本的な考え方は、boost_iterator(詳細はlinkを参照)を介して、ブーストの疎行列のすべての非ゼロ要素を反復することによってofstreamに書き込むことです。 ifstreamから読んだ場合、私は貧弱な人の方法を使用しています:書き込みフォーマットに従って繰り返し読み込み、疎の行列に挿入します。ここに私のテスト目的のために私のコードは次のとおりです。

#include <iostream> 
#include <fstream> 
#include <boost/numeric/ublas/matrix_sparse.hpp> 
#include <boost/numeric/ublas/io.hpp> 


    int main(int argc, char** argv) 
    { 
     using std::cerr; 
     using std::cout; 
     using std::endl; 
     using namespace boost::numeric::ublas; 
     typedef compressed_matrix<float, row_major> cMatrix; 

     const size_t size = 5; 
     const size_t rowInd[5] = { 0, 0, 1, 2, 4 }; 
     const size_t colInd[5] = { 0, 2, 0, 4, 4 }; 

     cMatrix sparseMat(size,size); 
     for (size_t i=0; i<size; ++i) 
      sparseMat.insert_element(rowInd[i], colInd[i], 1.0); 

     cout << sparseMat << endl; 

     // Try writing to file 
     std::ofstream ofsDat("temp.dat", std::ios::out | std::ios::binary); 
     for(cMatrix::const_iterator1 rowIter = sparseMat.begin1(); rowIter != sparseMat.end1(); ++rowIter) { 
      for(cMatrix::const_iterator2 colIter = rowIter.begin(); colIter != rowIter.end(); ++colIter) { 
       ofsDat << " " << colIter.index1() << " " << colIter.index2() << " " << *colIter; 
      }  // end for colIter 
     }  // end for rowIter 
     ofsDat.close(); 

     cout << "Writing ended, starting to read" << endl; 

     // Try reading the file 
     cMatrix sparseMat_2(size, size); 
     std::ifstream ifsDat("temp.dat", std::ios::in | std::ios::binary); 
     size_t rowTemp, colTemp; 
     float valTemp; 
     while(!ifsDat.eof()) { 
      ifsDat >> rowTemp >> colTemp >> valTemp; 
      cout << "row " << rowTemp << " column " << colTemp << " value " << valTemp << endl; 
      sparseMat_2.insert_element(rowTemp, colTemp, valTemp); 
     } 

     cout << sparseMat_2 << endl; 

     return 0; 
    } 

私はこれを行うには良い、または標準的な方法があるかどうかはわからない、セパレータなどのデータの間にスペースを追加しましたか?どんなフィードバックも高く評価されます!

+0

こんにちはYangLou。より高速なファイルシステムソリューションを探すには、行列が非常に大きく、非常に疎でなければなりません。そして、それらが非常にまばらでない限り、特にバイナリではなくテキストストリームを使用する場合、ここではほとんど得られません。 – lakeweb

+0

@lakeweb実際に行列は幾分大きく(65536 x 65536)、非ゼロ要素数は約20kです。私はバイナリ形式にio形式を変更しました、あなたはそれがioの速度を加速すると思いますか?私はデフォルトでテキストストリームが使用されることを知らなかった... – YangLou

+0

こんにちはYangLou。いいえ、 'ios :: binary'は' << '演算子の使用を変更しません。あなたの数字は、ストリームアウトされてもまだASCIIに変換されています。私の最初の例では、それらはバイナリとして書かれています、私はストリーミング演算子を使用していません。最適化する必要があるアプリケーション間で、非常に多くのデータを集中的にストリーミングしようとしていますか?もしそうなら、私は間違った方法でファイルシステムを使用します。私はこのレベルであなたがファイルシステムを使用することから得ている全体的なヒットにほとんど影響しないと確信しているので、プロファイラを実行するために一時的です。 – lakeweb