SkePU  1.2
 All Classes Namespaces Files Functions Variables Enumerations Friends Macros Groups Pages
sparse_matrix.h
Go to the documentation of this file.
1 
5 #ifndef _SPARSE_MATRIX_H
6 #define _SPARSE_MATRIX_H
7 
8 #include <cstdlib>
9 #include <map>
10 #include <string>
11 #include <fstream>
12 #include <sstream>
13 #include <vector>
14 #include <map>
15 #include <iomanip>
16 #include <set>
17 
18 #ifdef SKEPU_OPENCL
19 #ifdef USE_MAC_OPENCL
20 #include <OpenCL/opencl.h>
21 #else
22 #include <CL/cl.h>
23 #endif
25 #endif
26 
27 #ifdef SKEPU_CUDA
29 #endif
30 
31 #include "skepu/src/malloc_allocator.h"
32 #include "skepu/src/environment.h"
33 
34 
35 namespace skepu
36 {
37 
44 {
45  MATRIX_MARKET_FORMAT,
46  MATLAB_FORMAT,
47  RUTHERFOR_BOEING_FORMAT
48 };
49 
50 
72 template <class T>
74 {
75 
76 // typedefs
77 public:
78 #ifdef SKEPU_CUDA
81 #endif
82 
83 #ifdef SKEPU_OPENCL
86 #endif
87 
88 private:
89  T *m_values;
90  size_t *m_colInd;
91  size_t *m_rowPtr;
92  size_t m_rows;
93  size_t m_cols;
94  size_t m_nnz;
95  T m_zeroValue;
96  bool m_dealloc;
97 
98 // bool m_valid; /*! to keep track of whether the main copy is valid or not */
99 
100  // ***** RELATED to transpose of the matrix ****/
101  T *m_valuesCSC;
102  size_t *m_colPtrCSC;
103  size_t *m_rowIndCSC;
104  bool m_transposeValid;
105  SparseMatrix *m_cscMatrix;
106 
107 
108 
109 public:
110  class iterator;
111 
112  // following bool to is to control memory deallocation as we assign de-allocation responsibility to main matrix and not the transpose matrix itself.
113  bool m_transMatrix;
114 
115 private:
116 
117  void deleteCSCFormat() // when resizing so we need to take transpose again and also would have to allocate storgae again.
118  {
119  if(m_transMatrix) // do nothing then
120  return;
121 
122  m_transposeValid = false;
123 
124  if(m_colPtrCSC!=NULL)
125  {
126  delete m_colPtrCSC;
127  m_colPtrCSC = NULL;
128  }
129  if(m_rowIndCSC!=NULL)
130  {
131  delete m_rowIndCSC;
132  m_rowIndCSC = NULL;
133  }
134  if(m_valuesCSC!=NULL)
135  {
136  delete m_valuesCSC;
137  m_valuesCSC = NULL;
138  }
139 
140  if(m_cscMatrix!=NULL)
141  {
142  delete m_cscMatrix;
143  m_cscMatrix = NULL;
144  }
145  }
146 
147  void convertToCSCFormat()
148  {
149  if(m_transMatrix) // cannot transpose an already transposed
150  {
151  std::cerr<<"Cannot apply transpose operation on a matrix which is already in CSC format.\n";
152  SKEPU_EXIT();
153  }
154 
155  if(m_transposeValid && (m_valuesCSC!=NULL) && (m_rowIndCSC!=NULL) && (m_colPtrCSC!=NULL)) // already there
156  return;
157 
158  updateHost(); // update Host for new data;
159 
160  if(m_valuesCSC==NULL)
161  m_valuesCSC = new T[m_nnz];
162  if(m_rowIndCSC == NULL)
163  m_rowIndCSC = new size_t[m_nnz];
164  if(m_colPtrCSC == NULL)
165  m_colPtrCSC = new size_t[m_cols+1];
166 
167  size_t rowIdx = 0;
168  size_t nxtRowIdx = 0;
169 
170  std::multimap<size_t, std::pair<size_t, T>, std::less<size_t> > cscFormat;
171 
172  for(size_t ii = 0; ii < m_rows; ii++)
173  {
174  rowIdx = m_rowPtr[ii];
175  nxtRowIdx = m_rowPtr[ii+1];
176 
177  for(size_t jj=rowIdx; jj<nxtRowIdx; jj++)
178  {
179  cscFormat.insert( std::make_pair(m_colInd[jj], std::make_pair(ii, m_values[jj])) );
180  }
181  }
182 
183  // make multimap sorted based on key which is column index.
184  typedef typename std::multimap<size_t, std::pair<size_t, T>, std::less<size_t> >::iterator mapIter;
185  mapIter m_it, s_it;
186 
187  size_t col = 0, ind=0;
188 
189  m_colPtrCSC[0] = 0;
190 
191  size_t expColInd = 0; // assign it to first column index
192 
193  for (m_it = cscFormat.begin(); m_it != cscFormat.end(); m_it = s_it)
194  {
195  size_t colInd = (*m_it).first;
196 
197  if(expColInd < colInd) // meaning some intermediate columns are totally blank, i.e., no non-zero entries, add their record
198  {
199  for(size_t i=expColInd; i<colInd; i++)
200  {
201  m_colPtrCSC[++col] = ind;
202  }
203  }
204  expColInd = colInd+1; // now set expected to next column.
205 
206  std::pair<mapIter, mapIter> keyRange = cscFormat.equal_range(colInd);
207 
208  // Iterate over all map elements with key == theKey
209  for (s_it = keyRange.first; s_it != keyRange.second; ++s_it)
210  {
211  m_rowIndCSC[ind] = (*s_it).second.first;
212  m_valuesCSC[ind] = (*s_it).second.second;
213  ind++;
214  }
215  m_colPtrCSC[++col] = ind;
216  }
217  for(size_t i= (col+1); i<=m_cols; i++)
218  {
219  m_colPtrCSC[i] = ind;
220  }
221 
222  m_transposeValid = true;
223  }
224 
225 
226  void readMTXFile(const std::string &inputfile);
227 
228 public:
229 
230 // #if SKEPU_DEBUG>0
231  std::string m_nameVerbose; // for debugging useful
232 // #endif
233 
234  void printMatrixInDenseFormat()
235  {
236  std::cerr<<"SparseMatrix ("<<m_rows <<" X "<< m_cols<<") nnz: "<<m_nnz<<"\n";
237 
238  T *temp = new T[m_cols];
239 
240  size_t rowIdx, nxtRowIdx;
241  for(size_t ii = 0; ii < m_rows; ii++)
242  {
243  for(size_t i=0; i<m_cols; i++)
244  temp[i] = T();
245 
246  rowIdx = m_rowPtr[ii];
247  nxtRowIdx = m_rowPtr[ii+1];
248 
249  for(size_t jj=rowIdx; jj<nxtRowIdx; jj++)
250  {
251  temp[m_colInd[jj]] = m_values[jj];
252  }
253 
254  for(size_t i=0; i<m_cols; i++)
255  std::cerr<<std::setw(5)<<temp[i];
256 
257  std::cerr<<"\n";
258  }
259 
260  delete[] temp;
261  }
262 
263  // unary CSC operator
264  inline SparseMatrix<T>& operator~()
265  {
266  convertToCSCFormat();
267 
268  if(m_cscMatrix==NULL)
269  {
270  m_cscMatrix = new SparseMatrix(m_cols, m_rows, m_nnz, m_valuesCSC, m_colPtrCSC, m_rowIndCSC, false, T(), true);
271  }
272 
273  return *m_cscMatrix;
274  }
275 
276  // ----- CONSTRUCTORS & DESTRUCTORS -------//
277  SparseMatrix(size_t rows, size_t cols, size_t nnz, T *values, size_t *rowPtr, size_t *colInd, bool dealloc=true, T zeroValue=T(), bool transMatrix=false);
278 
279  SparseMatrix(size_t rows, size_t cols, size_t nnz, T min, T max, T zeroValue=T());
280 
281  SparseMatrix(const SparseMatrix &copy);
282 
283  SparseMatrix(const std::string &inputfile, enum SparseFileFormat format=MATRIX_MARKET_FORMAT, T zeroValue=T());
284 
285  ~SparseMatrix();
286 
287  void operator=(const SparseMatrix<T> &copy);
288 
289  // ----- FRIEND METHODS -------//
290 
296  friend std::ostream& operator<<(std::ostream &os, SparseMatrix<T>& matrix)
297  {
298  matrix.updateHost();
299 
300  os<<"Matrix rows="<< matrix.total_rows() <<", cols="<<matrix.total_cols()<<", nnz="<<matrix.total_nnz()<<"\n";
301 
302  size_t rowIdx = 0;
303  size_t nxtRowIdx = 0;
304 
305  for(size_t ii = 0; ii < matrix.total_rows(); ii++)
306  {
307  rowIdx = matrix.m_rowPtr[ii];
308  nxtRowIdx = matrix.m_rowPtr[ii+1];
309 
310  for(size_t jj=rowIdx; jj<nxtRowIdx; jj++)
311  {
312  os<< "row: "<<std::setw(8)<<ii<<", col: "<<std::setw(8)<<matrix.m_colInd[jj]<<", value"<<std::setw(12)<<matrix.m_values[jj]<<"\n";
313  }
314  }
315 
316  os<<"\n";
317  return os;
318  }
319 
320 
321 public:
322 
327  size_t total_nnz() const
328  {
329  return m_nnz;
330  }
331 
336  size_t total_rows() const
337  {
338  return m_rows;
339  }
340 
345  size_t total_cols() const
346  {
347  return m_cols;
348  }
349 
354  T* get_values() const
355  {
356  return m_values;
357  }
358 
359  size_t* get_row_pointers() const
360  {
361  return m_rowPtr;
362  }
363 
364  size_t* get_col_indices() const
365  {
366  return m_colInd;
367  }
368 
369  size_t get_rowSize(size_t row) const
370  {
371  return (m_rowPtr[row+1]-m_rowPtr[row]);
372  }
373 
374  size_t get_rowOffsetFromStart(size_t row) const
375  {
376  if(row<total_rows())
377  return m_rowPtr[row];
378 
379  return m_nnz;
380  }
381 
382 public:
383 
384  iterator begin(unsigned row);
385 
386  // Element access using 'at' operator
387  T at(size_t row, size_t col ) const;
388  const T& at(size_t index) const;
389 
390  // Similar to 'at' operator but don't do memory check etc. must faster used internally in implementation.
391  const T& at_internal(size_t row, size_t col ) const;
392  T& at_internal(size_t row, size_t col );
393  const T& at_internal(size_t index) const;
394 
395  // Element access using () operator
396  const T& operator()(const size_t row, const size_t col) const;
397  T operator()(const size_t row, const size_t col);
398 
399  // will resize the matrix, can be dangerous, used with care
400  void resize(SparseMatrix<T> &copy, bool retainData);
401 
402  void updateHost() const;
403  void invalidateDevice();
405 
406 #ifdef SKEPU_OPENCL
407  device_pointer_type_cl updateDevice_CL(T* start, size_t elems, Device_CL* device, bool copy);
408  device_pointer_index_type_cl updateDevice_Index_CL(size_t* start, size_t elems, Device_CL* device, bool copy);
409  void flush_CL();
410 #endif
411 
412 #ifdef SKEPU_CUDA
413  device_pointer_type_cu updateDevice_CU(T* start, size_t elems, unsigned int deviceID, bool copy);
414  device_pointer_index_type_cu updateDevice_Index_CU(size_t* start, size_t elems, unsigned int deviceID, bool copy);
415  void flush_CU();
416  bool isSparseMatrixOnDevice_CU(unsigned int deviceID);
417  bool isModified_CU(unsigned int deviceID);
418 #endif
419 
420 
421 private:
422 
423 #ifdef SKEPU_OPENCL
424  void updateHost_CL() const;
425  void invalidateDeviceData_CL();
426  void releaseDeviceAllocations_CL();
427 #endif
428 
429 #ifdef SKEPU_CUDA
430  void updateHost_CU() const;
431  void invalidateDeviceData_CU();
432  void releaseDeviceAllocations_CU();
433 #endif
434 
435 #ifdef SKEPU_CUDA
436  std::map<std::pair< unsigned int, std::pair< T*, size_t > >, device_pointer_type_cu > m_deviceMemPointers_CU;
437  std::map<std::pair< unsigned int, std::pair< size_t*, size_t > >, device_pointer_index_type_cu > m_deviceMemIndexPointers_CU;
438 #endif
439 
440 #ifdef SKEPU_OPENCL
441  std::map<std::pair< cl_device_id, std::pair< T*, size_t > >, device_pointer_type_cl > m_deviceMemPointers_CL;
442  std::map<std::pair< cl_device_id, std::pair< size_t*, size_t > >, device_pointer_index_type_cl > m_deviceMemIndexPointers_CL;
443 #endif
444 
445 
446 }; // end class SparseMatrix
447 
448 
449 } // end namespace skepu
450 
451 
453 
454 
455 #include "src/sparse_matrix.inl"
456 
457 #ifdef SKEPU_OPENCL
458 #include "src/sparse_matrix_cl.inl"
459 #endif
460 
461 #ifdef SKEPU_CUDA
462 #include "src/sparse_matrix_cu.inl"
463 #endif
464 
465 #endif /* _MATRIX_H */
466 
Contains the definitions of the SparseMatrix::iterator class.
device_pointer_index_type_cu updateDevice_Index_CU(size_t *start, size_t elems, unsigned int deviceID, bool copy)
Update device with sparse matrix index contents that have an &quot;size_t&quot; type.
Definition: sparse_matrix_cu.inl:82
Contains a class declaration for an object which represents an OpenCL device memory allocation for co...
Contains a class declaration for an object which represents an CUDA device memory allocation for Vect...
void resize(SparseMatrix< T > &copy, bool retainData)
Definition: sparse_matrix.inl:431
size_t total_cols() const
Definition: sparse_matrix.h:345
void flush_CL()
Flushes the sparse matrix.
Definition: sparse_matrix_cl.inl:123
size_t total_nnz() const
Definition: sparse_matrix.h:327
void flush_CU()
Flushes the matrix.
Definition: sparse_matrix_cu.inl:128
A sparse matrix container class that mainly stores its data in CSR format.
Definition: sparse_matrix.h:73
void updateHostAndInvalidateDevice()
Definition: sparse_matrix.inl:639
~SparseMatrix()
Definition: sparse_matrix.inl:244
A class representing an OpenCL device memory allocation for container.
Definition: device_mem_pointer_cl.h:38
T at(size_t row, size_t col) const
Definition: sparse_matrix.inl:296
T min(T a, T b)
Definition: mapoverlap_convol_kernels.h:212
device_pointer_type_cl updateDevice_CL(T *start, size_t elems, Device_CL *device, bool copy)
Update device with sparse matrix content.
Definition: sparse_matrix_cl.inl:25
iterator begin(unsigned row)
Definition: sparse_matrix.inl:346
T max(T a, T b)
Definition: mapoverlap_convol_kernels.h:203
size_t total_rows() const
Definition: sparse_matrix.h:336
device_pointer_type_cu updateDevice_CU(T *start, size_t elems, unsigned int deviceID, bool copy)
Update device with matrix content.
Definition: sparse_matrix_cu.inl:26
An sparse matrix iterator class that tranverses row-wise.
Definition: sparse_matrix_iterator.inl:20
Contains the definitions of member functions of the SparseMatrix class related to CUDA backend...
bool isModified_CU(unsigned int deviceID)
Definition: sparse_matrix_cu.inl:191
void updateHost() const
Definition: sparse_matrix.inl:609
void invalidateDevice()
Definition: sparse_matrix.inl:624
void operator=(const SparseMatrix< T > &copy)
Definition: sparse_matrix.inl:191
bool isSparseMatrixOnDevice_CU(unsigned int deviceID)
Definition: sparse_matrix_cu.inl:208
A class representing a CUDA device memory allocation for container.
Definition: device_mem_pointer_cu.h:58
Contains a class declaration for Environment class.
SparseFileFormat
Can be used to specify the input format for a sparse matrix that is supplied in constructor.
Definition: sparse_matrix.h:43
Contains the definitions of member functions of the SparseMatrix class related to OpenCL backend...
const T & operator()(const size_t row, const size_t col) const
Definition: sparse_matrix.inl:367
Contains the definitions of member functions of the SparseMatrix class that are not related to any ba...
T * get_values() const
Definition: sparse_matrix.h:354
device_pointer_index_type_cl updateDevice_Index_CL(size_t *start, size_t elems, Device_CL *device, bool copy)
Update device with sparse matrix index contents that have an &quot;size_t&quot; type.
Definition: sparse_matrix_cl.inl:80
SparseMatrix(size_t rows, size_t cols, size_t nnz, T *values, size_t *rowPtr, size_t *colInd, bool dealloc=true, T zeroValue=T(), bool transMatrix=false)
Definition: sparse_matrix.inl:29