1

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

  • I'm pretty sure you can go from array2d to coo matrix or probably ell matrix. The constructors for coo matrix and [ell matrix](http://docs.cusp-library.googlecode.com/hg/classcusp_1_1ell__matrix.html) know how to interpret other matrix types. Here's a [worked example](http://cusp-library.googlecode.com/svn-history/r79/trunk/testing/io.cu) going directly from array2d to coo matrix. – Robert Crovella Feb 21 '13 at 21:38
  • Thanks Robert. I just edited my question to state the fact that I got rid of the exception, although I am not sure in a right way. The examples in the link you provided can spare me the headache of writing back and forth to disk. I will check and see if the results are the same. Thanks. – Mai El-Chehaly Feb 21 '13 at 22:15

2 Answers2

1

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;
 }
Robert Crovella
  • 143,785
  • 11
  • 213
  • 257
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";
          }
        }
        }
  • Perhaps you are using an older version of cusp. I just cloned cusp from git and the file `cusp/io/detail/matrix_market.inl` does not have this issue: [it is showing `mtx.num_rows` on the inner loop](https://github.com/cusplibrary/cusplibrary/blob/master/cusp/io/detail/matrix_market.inl). It looks like [this issue was fixed 10 months ago](https://github.com/cusplibrary/cusplibrary/tree/master/cusp/io/detail). – Robert Crovella Feb 22 '13 at 05:41