简体   繁体   中英

cusp::io::write_matrix_market_file() gives Access Violation Exception

I am trying to read a 272 x 544 double matrix from Matlab into an ELLPACK format sparse matrix using CUSP. The only way I can find so far is to read the data into mxArray, read the mxArray into a double* array (using mxGetPr()), then copy the values into cusp::array2d. Once there, I need to write the array2d to a .mtx file then read the file into coo_matrix and finally convert that to ell_matrix. It sounds silly even to me but given the little documentation for CUSP, this is the best I could think of. I would be very very thankful if someone recommends a better way to do it.

Anyway, the problem I am facing right now is that after I read the data in array2d and I try to write it to .mtx file using cusp::write_matrix_market_file() I get an "unhandled exception: access violation for writing location" error message. I tried printing some values from the array2d before I try to write them to file, just to make sure everything is in place and the values seem to be stored fine in the array2d. I also tried changing the type to float, but the error persists. Here is my code for this task:

     #include <thrust/version.h>
     #include <cusp/version.h>
     #include <cusp/ell_matrix.h>
     #include <cusp/print.h>
     #include <cusp/io/matrix_market.h>
     #include <cusp/array2d.h>
     #include <cusp/coo_matrix.h>

     int main(int argc, char** argv)
     {
      const mxArray* mx_g_tra;
      //Reading data from Matlab   
       mx_g_tra = openMatFile2("C:\\out.mat", ndir, "out.tra");
   double* g_tra = mxGetPr(mx_g_tra);
   sizeG_tra=(int)mxGetNumberOfElements(mx_g_tra);
   const mwSize* traDims= mxGetDimensions(mx_g_tra);

      //get matrix dimensions
       tra_W= traDims[0];
   tra_H= traDims[1];
   printf("\nAcquired %d TRA elements as %d x %d from Maltab.\n", sizeG_tra, tra_W, tra_H);
       cusp::array2d<float, cusp::host_memory> TRA(traDims[0], traDims[1]);
       if(g_tra != NULL)
       {
       for(int i=0; i< traDims[0]; i++)
        {
         for(int j=0; j<traDims[1]; j++) 
          {TRA(i,j) = (float)g_tra[i*traDims[1]+j];
           if(TRA(i,j) != 0) printf("\nTRA(%d, %d) = %g", i, j, TRA(i,j));}
        }
       }

 cusp::io::write_matrix_market_file(TRA, "C:\\TRA.mtx"); 

At the time I get the exception, the call stack points to: cusp::io::detail::write_value >,float>(std::basic_ofstream > & output={...}, const float & value=) Line 116 + 0x5 bytes C++

Edit: Quick Update: I got rid of the exception by modifying the file "matrix_market.inl" they had a weird nested loop that writes values to file by looping over matrix cols then cols again (num_rows is never considered) Obviously since my matrix is not square, the code was trying to access unexisting locations.. Here is the modified code:

      for(size_t j = 0; j < mtx.num_cols; j++)
       {
    // Modified below: mtx.num_cols --> mtx.num_rows
         for(size_t i = 0; i < mtx.num_rows; i++)
         {
         write_value(output, mtx(i,j));
         output << "\n";
          }
         }

I am not sure how this affects the different format constructors when reading from this .mtx file though

This code worked for me, demonstrating how to go directly from array2d to coo or ell:

EDIT: updated code sample to show usage of cusp::is_valid_matrix()

 #include <stdio.h>
 #include <cusp/verify.h>
 #include <cusp/ell_matrix.h>
 #include <cusp/io/matrix_market.h>
 #include <cusp/array2d.h>
 #include <cusp/coo_matrix.h>

 int main(int argc, char** argv)
 {
  // initial matrix
   cusp::array2d<float, cusp::host_memory> E(4, 3);
   E(0,0) =  1.000e+00; E(0,1) =  0.000e+00; E(0,2) =  0.000e+00;
   E(1,0) =  0.000e+00; E(1,1) =  1.050e+01; E(1,2) =  0.000e+00;
   E(2,0) =  0.000e+00; E(2,1) =  0.000e+00; E(2,2) =  2.500e-01;
   E(3,0) =  0.000e+00; E(3,1) =  2.505e+02; E(3,2) =  0.000e+00;

   cusp::coo_matrix<int, float, cusp::host_memory> coo(E);
   cusp::ell_matrix<int, float, cusp::host_memory> ell(E);
   if (!cusp::is_valid_matrix(coo)) {printf("Invalid COO\n"); return 1;}
   if (!cusp::is_valid_matrix(ell)) {printf("Invalid ELL\n"); return 1;}

   cusp::io::write_matrix_market_file(coo, "COO.mtx");
   cusp::io::write_matrix_market_file(ell, "ELL.mtx");
   return 0;
 }

As long as the number of rows is greater than the number of cols, there is no exception and no problem with the code. The problem I had was because the number of rows is half the number of cols. So when write_value in file "matrix_market.inl" assumed that my matrix is a square matrix and only considered num_cols in both loops, I got the error. In fact, the value of i at the time the exception was thrown was 273 (the first row that does not exist in my 272 x 544 matrix). I fixed it by editing write_matrix_market_stream in "matrix_market.inl" code as follows:

       template <typename Matrix, typename Stream>
       void write_matrix_market_stream(const Matrix& mtx, Stream& output, cusp::array2d_format)
       {
        typedef typename Matrix::value_type ValueType;

        bool is_complex = thrust::detail::is_same<ValueType, cusp::complex<typename                   norm_type<ValueType>::type> >::value;

        if (is_complex)
        output << "%%MatrixMarket matrix array complex general\n";
        else
        output << "%%MatrixMarket matrix array real general\n";

        output << "\t" << mtx.num_rows << "\t" << mtx.num_cols << "\n";

        for(size_t j = 0; j < mtx.num_cols; j++)
        {
         // EDIT needed here
     // Modified below: mtx.num_cols --> mtx.num_rows
        for(size_t i = 0; i < mtx.num_rows; i++)
          {
             write_value(output, mtx(i,j));
            output << "\n";
          }
        }
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM