2016-12-20 2 views
0

친애 유래 커뮤니티 :쓰기 BOOST 희소 행렬

내가 밀어주는 아주 새로운 해요, 나는 그 uBLAS 라이브러리의 스파 스 매트릭스를 사용하는 것을 시도하고있다. 필자가 마주 치게되는 한 가지 문제는 스파 스 매트릭스를 계산 한 후이를 바이너리 파일에 저장하고 다른 프로그램에서 파일을 읽고 스파 스 매트릭스를 복구하는 것입니다. 일반적으로 나는 다음과 같은 방법으로 파일을 작성 (예를 들어 내가 100 개 수레와 배열 A를 경우) :

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

나는 BOOST 희소 행렬 비슷한 쓰기 작업을 할 수 있을지 궁금하네요을? 그렇다면 ofstream :: write의 두 번째 인수는 무엇이되어야 하는가? (데이터 청크의 크기 여야 함)

답변

0

부스트 스파 스 매트릭스는 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이 0 인 희소 2D 행렬 (NxN)의 경우 두 개의 루프를 수행하는 복잡성이 N^2이지만이 쓰기 작업은 실제로는 0이 아닌 요소에 대한 M 개의 액세스 만 필요로합니다. 그렇다면 0이 아닌 요소를 모두 효율적으로 반복 할 수있는 방법이 있습니까? – YangLou

+0

이 링크가 발견되었습니다. [link] (http://stackoverflow.com/questions/1795658/looping-over-the-non-zero-elements-of-a-ublas-sparse-matrix) 0이 아닌 모든 원소를 반복하여 0이 아닌 모든 원소를 반복하려면? 아니면 여기에 뭔가 빠졌나요? – YangLou

+0

안녕하세요 @ YangLou. 프로파일 러를 점검하지는 않았지만, 파일을 작성하고 0을 채우기 때문에 데이터를 얻는 것이 병목 목에 중요하지 않습니다. 스파 스 매트릭스를 사용하면 매트릭스에서 더 빠르게 계산할 수 있습니다. – lakeweb

0

마지막으로 몇 가지 검색 및 시도를 한 후에는이 작업을 수행하고 스파 스 매트릭스를 읽는 방법을 발견했습니다. 내 작업은 실제로 비교적 간단하므로 더 복잡하고 좀 더 일반적인 목적을 위해이 조잡한 방법이 효과적인지 아닌지를 알지 못합니다.

기본적인 아이디어는 부스트의 희소 행렬에있는 모든 0이 아닌 요소를 const_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), 0이 아닌 원소 수는 약 20k입니다. 바이너리 형식으로 io 형식을 변경 했으므로 io 속도가 빨라질 것이라고 생각하십니까? 나는 기본적으로 텍스트 스트림이 사용될 것임을 몰랐습니다 ... – YangLou

+0

안녕 YangLou. 아니요,'ios :: binary '는'<<'연산자의 사용을 변경하지 않습니다. 귀하의 전화 번호는 스트리밍 될 때 여전히 ASCII로 변환됩니다. 첫 번째 예제에서는 바이너리로 쓰여지고 스트리밍 연산자는 사용하지 않습니다. 최적화해야하는 애플리케이션간에 너무 많은 데이터를 집중적으로 스트리밍하려고합니까? 그렇다면 파일 시스템을 사용하는 것이 잘못된 접근입니다. 이 레벨에서 수행하는 작업이 파일 시스템 사용으로 인해 발생하는 전반적인 영향에 거의 영향을 미치지 않을 것으로 확신하므로 프로파일 러를 실행하도록 임시 처리됩니다. – lakeweb