SkePU(integratedwithStarPU)  0.8.1
 All Classes Namespaces Files Functions 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 <iostream>
9 #include <fstream>
10 #include <sstream>
11 #include <cstdlib>
12 
13 #include <vector>
14 
15 #include <map>
16 
17 #include <iomanip>
18 
19 #include <starpu.h>
20 
21 #include "skepu/src/debug.h"
22 
23 #include "skepu/src/malloc_allocator.h"
24 
25 
26 
27 
28 
29 namespace skepu
30 {
31 
38  {
39  MATRIX_MARKET_FORMAT,
40  MATLAB_FORMAT,
41  RUTHERFOR_BOEING_FORMAT
42  };
43 
44 
61 template<typename T>
63 {
64 
65 public:
66  T *m_values;
67  unsigned int *m_colInd;
68  unsigned int *m_rowPtr;
69  unsigned int m_rows;
70  unsigned int m_cols;
71  unsigned int m_nnz;
72  T m_zeroValue;
73  bool m_dealloc;
74 
75 
76 
77 // ***** RELATED to transpose of the matrix ****/
78  T *m_valuesCSC;
79  unsigned int *m_colPtrCSC;
80  unsigned int *m_rowIndCSC;
81  bool m_transposeValid;
82  SparseMatrix *m_cscMatrix;
83 
84  // following bool to is to control memory deallocation as we assign de-allocation responsibility to main matrix and not the transpose matrix itself.
85  bool m_transMatrix;
86 
87 
88 public:
89  class iterator;
90 
91 private: //private:
92  void deleteCSCFormat() // when resizing so we need to take transpose again and also would have to allocate storgae again.
93  {
94  if(m_transMatrix) // do nothing then
95  return;
96 
97 
98  m_transposeValid = false;
99 
100  if(m_colPtrCSC!=NULL)
101  {
102  delete m_colPtrCSC;
103  m_colPtrCSC = NULL;
104  }
105  if(m_rowIndCSC!=NULL)
106  {
107  delete m_rowIndCSC;
108  m_rowIndCSC = NULL;
109  }
110  if(m_valuesCSC!=NULL)
111  {
112  delete m_valuesCSC;
113  m_valuesCSC = NULL;
114  }
115 
116  if(m_cscMatrix!=NULL)
117  {
118  delete m_cscMatrix;
119  m_cscMatrix = NULL;
120  }
121  }
122 
123  void convertToCSCFormat()
124  {
125  if(m_transMatrix) // cannot transpose an already transposed
126  {
127  std::cerr<<"Cannot apply transpose operation on a matrix which is already in CSC format.\n";
128  SKEPU_ABORT();
129  }
130 
131  if(m_transposeValid && (m_valuesCSC!=NULL) && (m_rowIndCSC!=NULL) && (m_colPtrCSC!=NULL)) // already there
132  return;
133 
134  updateHost(); // update Host for new data;
135 
136  if(m_valuesCSC==NULL)
137  m_valuesCSC = new T[m_nnz];
138  if(m_rowIndCSC == NULL)
139  m_rowIndCSC = new unsigned int[m_nnz];
140  if( m_colPtrCSC == NULL)
141  m_colPtrCSC = new unsigned int[m_cols+1];
142 
143  int rowIdx = 0;
144  int nxtRowIdx = 0;
145 
146  std::multimap<unsigned int, std::pair<unsigned int, T>, std::less<unsigned int> > cscFormat;
147 
148  for(int ii = 0; ii < m_rows; ii++)
149  {
150  rowIdx = m_rowPtr[ii];
151  nxtRowIdx = m_rowPtr[ii+1];
152 
153  for(int jj=rowIdx; jj<nxtRowIdx; jj++)
154  {
155  cscFormat.insert( std::make_pair(m_colInd[jj], std::make_pair(ii, m_values[jj])) );
156  }
157  }
158 
159  // make multimap sorted based on key which is column index.
160  typedef typename std::multimap<unsigned int, std::pair<unsigned int, T>, std::less<unsigned int> >::iterator mapIter;
161  mapIter m_it, s_it;
162 
163  int col = 0, ind=0;
164 
165  m_colPtrCSC[0] = 0;
166 
167  unsigned int expColInd = 0; // assign it to first column index
168 
169  for (m_it = cscFormat.begin(); m_it != cscFormat.end(); m_it = s_it)
170  {
171  unsigned int colInd = (*m_it).first;
172 
173  if(expColInd < colInd) // meaning some intermediate columns are totally blank, i.e., no non-zero entries, add their record
174  {
175  for(int i=expColInd; i<colInd; i++)
176  {
177  m_colPtrCSC[++col] = ind;
178  }
179  }
180  expColInd = colInd+1; // now set expected to next column.
181 
182  std::pair<mapIter, mapIter> keyRange = cscFormat.equal_range(colInd);
183 
184  // Iterate over all map elements with key == theKey
185  for (s_it = keyRange.first; s_it != keyRange.second; ++s_it)
186  {
187  m_rowIndCSC[ind] = (*s_it).second.first;
188  m_valuesCSC[ind] = (*s_it).second.second;
189  ind++;
190  }
191  m_colPtrCSC[++col] = ind;
192  }
193  for(int i= (col+1); i<=m_cols; i++)
194  {
195  m_colPtrCSC[i] = ind;
196  }
197 
198  m_transposeValid = true;
199  }
200 
201 
202  void readMTXFile(const std::string &inputfile);
203 
204 public:
205 
206  void printMatrixInDenseFormat()
207  {
208  std::cerr<<"SparseMatrix ("<<m_rows <<" X "<< m_cols<<") nnz: "<<m_nnz<<"\n";
209 
210  T *temp = new T[m_cols];
211 
212  int rowIdx, nxtRowIdx;
213  for(int ii = 0; ii < m_rows; ii++)
214  {
215  for(int i=0; i<m_cols; i++)
216  temp[i] = T();
217 
218  rowIdx = m_rowPtr[ii];
219  nxtRowIdx = m_rowPtr[ii+1];
220 
221  for(int jj=rowIdx; jj<nxtRowIdx; jj++)
222  {
223  temp[m_colInd[jj]] = m_values[jj];
224  }
225  for(int i=0; i<m_cols; i++)
226  std::cerr<<std::setw(5)<<temp[i];
227 
228  std::cerr<<"\n";
229  }
230 
231  delete[] temp;
232  }
233 
234  // unary CSC operator
235  inline SparseMatrix<T>& operator~()
236  {
237  convertToCSCFormat();
238 
239  if(m_cscMatrix==NULL)
240  {
241  m_cscMatrix = new SparseMatrix(m_cols, m_rows, m_nnz, m_valuesCSC, m_colPtrCSC, m_rowIndCSC, false, T(), true);
242  }
243 
244  return *m_cscMatrix;
245  }
246 
247 // ----- CONSTRUCTORS & DESTRUCTORS -------//
248  SparseMatrix(unsigned int rows, unsigned int cols, unsigned int nnz, T *values, unsigned int *rowPtr, unsigned int *colInd, bool dealloc=true, T zeroValue=T(), bool transMatrix=false);
249 
250  SparseMatrix(unsigned int rows, unsigned int cols, unsigned int nnz, T min, T max, T zeroValue=T());
251 
252  SparseMatrix(const SparseMatrix &copy);
253 
254  SparseMatrix(const std::string &inputfile, enum SparseFileFormat format=MATRIX_MARKET_FORMAT, T zeroValue=T());
255 
256  ~SparseMatrix();
257 
258 
259 // ----- FRIEND METHODS -------//
260 
266  friend std::ostream& operator<<(std::ostream &os, SparseMatrix<T>& matrix)
267  {
268  matrix.acquireRead();
269 
270  os<<"Matrix rows="<< matrix.total_rows() <<", cols="<<matrix.total_cols()<<", nnz="<<matrix.total_nnz()<<"\n";
271 
272  int rowIdx = 0;
273  int nxtRowIdx = 0;
274 
275  for(int ii = 0; ii < matrix.total_rows(); ii++)
276  {
277  rowIdx = matrix.m_rowPtr[ii];
278  nxtRowIdx = matrix.m_rowPtr[ii+1];
279 
280  for(int jj=rowIdx; jj<nxtRowIdx; jj++)
281  {
282  os<< "row: "<<std::setw(8)<<ii<<", col: "<<std::setw(8)<<matrix.m_colInd[jj]<<", value"<<std::setw(12)<<matrix.m_values[jj]<<"\n";
283  }
284  }
285 
286  os<<"\n";
287  return os;
288  }
289 
290 
291 public:
292 
297  unsigned int total_nnz() const { return m_nnz;}
298 
303  unsigned int total_rows() const {return m_rows; }
304 
309  unsigned int total_cols() const {return m_cols; }
310 
315  T* get_values() { /* unregisterSparseMatrix(); */ acquireReadWrite(); return m_values; }
316 
317  unsigned int* get_row_pointers() const {return m_rowPtr; }
318 
319  unsigned int* get_col_indices() const {return m_colInd; }
320 
321  int get_rowSize(unsigned int row) const
322  {
323  return (m_rowPtr[row+1]-m_rowPtr[row]);
324  }
325 
326  int get_rowOffsetFromStart(unsigned int row) const
327  {
328  if(row<total_rows())
329  return m_rowPtr[row];
330  return m_nnz;
331  }
332 
333 public:
334 
335  iterator begin(unsigned row);
336 
337  // Element access using 'at' operator
338  T at(unsigned int row, unsigned int col ) const;
339  const T& at(unsigned int index) const;
340 
341  // Similar to 'at' operator but don't do memory check etc. must faster used internally in implementation.
342  const T& at_internal(unsigned int row, unsigned int col ) const;
343  T& at_internal(unsigned int row, unsigned int col );
344  const T& at_internal(unsigned int index) const;
345 
346  // Element access using () operator
347  const T& operator()(const unsigned int row, const unsigned int col) const;
348  T operator()(const unsigned int row, const unsigned int col);
349 
350  // will resize the matrix, can be dangerous, used with care
351  void resize(SparseMatrix<T> &copy, bool retainData);
352 
353  void updateHost() const;
354  void invalidateDevice();
355  void updateHostAndInvalidateDevice();
356 
357 
358  void acquireRead() const;
359  void acquireReadWrite();
360 
361 private:
362 
363  void unpartitionMatrix() const
364  {
365  DEBUG_TEXT_LEVEL1("***** SPARSE MATRIX UNPARTIOTIINING parts: "<< parts <<" *****\n")
366 
367  if(parts>1)
368  starpu_data_unpartition(csr_matrix_handle, 0); // need to check as it might only unpartition only one filter.
369 
370  parts=1;
371  }
372 
376  void release_acquire()
377  {
378  if(isAcquire)
379  {
380  if(parts>1) // partitioning
381  {
382  DEBUG_TEXT_LEVEL1("***** SPARSE MATRIX RELEASE **** parts: "<< parts <<"\n")
383 
384  // parts should be equal to what parts variable points to
385  assert (parts == starpu_data_get_nb_children(csr_matrix_handle));
386  for (int x = 0; x < parts; x++)
387  {
388  starpu_data_release(starpu_data_get_sub_data(csr_matrix_handle, 1, x));
389  }
390  }
391  else // no partitioning
392  {
393  DEBUG_TEXT_LEVEL1("***** SPARSE MATRIX RELEASE ****\n")
394  starpu_data_release(csr_matrix_handle);
395  }
396  isAcquire = false;
397  }
398  }
399 
400 
401 public:
402 
403  starpu_data_handle_t csr_matrix_handle;
404  mutable bool isOnStarPU;
405  mutable bool isReadBack;
406  mutable bool isWriteBack;
407  mutable int parts; // partitioning
408 
409  mutable bool isAcquire;
410  mutable enum starpu_data_access_mode mode;
411 
412  struct starpu_data_filter csr_matrix_filter;
413 
414 
418  starpu_data_handle_t registerSparseMatrix()
419  {
420  release_acquire();
421 
422  if(!isOnStarPU)
423  {
424  starpu_csr_data_register(&csr_matrix_handle,0, m_nnz, m_rows, (uintptr_t)m_values, (uint32_t *)m_colInd, (uint32_t *)m_rowPtr, 0, sizeof(m_values[0]));
425  isOnStarPU=true;
426  DEBUG_TEXT_LEVEL1("***** SPARSE MATRIX REGISTERING **** rows: "<< m_rows <<" cols: "<< m_cols <<" \n")
427  }
428  else if(parts>1)
429  {
430  unpartitionMatrix();
431  }
432  return csr_matrix_handle;
433  }
434 
438  void unregisterSparseMatrix(bool update=true)
439  {
440  if(isOnStarPU)
441  {
442  release_acquire(); // Should we release before unregister? Yes!
443 
444  if(parts>1) // do we need to unpartition before unregistering? Yes!
445  {
446  unpartitionMatrix();
447  }
448 
449  if(update)
450  starpu_data_unregister(csr_matrix_handle);
451 
452  else // dont need to get updated data back
453  starpu_data_unregister_no_coherency(csr_matrix_handle);
454 
455  isOnStarPU = false;
456  isAcquire = false;
457  }
458  }
459 
463  starpu_data_handle_t registerPartitions(int _parts=1)
464  {
465  release_acquire();
466 
467  if(!isOnStarPU) // if not registered, register it first
468  {
469  starpu_csr_data_register(&csr_matrix_handle,0, m_nnz, m_rows, (uintptr_t)m_values, (uint32_t *)m_colInd, (uint32_t *)m_rowPtr, 0, sizeof(m_values[0]));
470  isOnStarPU=true;
471  DEBUG_TEXT_LEVEL1("***** SPARSE MATRIX REGISTERING **** "<< m_nnz <<"\n")
472  parts=1;
473  }
474 
475  if(_parts == parts)
476  return csr_matrix_handle;
477 
478  if(parts>1)
479  {
480  starpu_data_unpartition(csr_matrix_handle, 0); // first unpartition previous partitioning.
481  DEBUG_TEXT_LEVEL1("***** SPARSE MATRIX UNPARTITIONING **** parts: "<< parts <<"\n")
482  parts = 1;
483  }
484  if(_parts>1)
485  {
486  csr_matrix_filter.nchildren = _parts;
487  starpu_data_partition(csr_matrix_handle, &csr_matrix_filter);
488 
489  parts = _parts;
490 
491  DEBUG_TEXT_LEVEL1("***** SPARSE MATRIX PARTITIONING **** parts: "<< _parts <<"\n")
492  }
493 
494  return csr_matrix_handle;
495  }
496 };
497 
498 }
499 
501 
502 #include "src/sparse_matrix.inl"
503 
504 #endif
505 
506 
Contains the definitions of the SparseMatrix::iterator class.
void acquireReadWrite()
Ensure that data is available for reading and writing purpose on CPU First updates the SparseMatrix f...
Definition: sparse_matrix.inl:679
void resize(SparseMatrix< T > &copy, bool retainData)
Definition: sparse_matrix.inl:457
Defines a few macros that can be used to output text when debugging. The macros use std::cerr...
starpu_data_handle_t registerPartitions(int _parts=1)
To register Matrix to StarPU. This method can create partitions of the matrix.
Definition: sparse_matrix.h:463
SparseMatrix(unsigned int rows, unsigned int cols, unsigned int nnz, T *values, unsigned int *rowPtr, unsigned int *colInd, bool dealloc=true, T zeroValue=T(), bool transMatrix=false)
Definition: sparse_matrix.inl:65
unsigned int total_rows() const
Definition: sparse_matrix.h:303
A sparse matrix container class that mainly stores its data in CSR format.
Definition: sparse_matrix.h:62
~SparseMatrix()
Definition: sparse_matrix.inl:264
void unregisterSparseMatrix(bool update=true)
Definition: sparse_matrix.h:438
void acquireRead() const
Ensure that SparseMatrix data is most updated for reading purpose on CPU.
Definition: sparse_matrix.inl:646
iterator begin(unsigned row)
Definition: sparse_matrix.inl:367
unsigned int total_cols() const
Definition: sparse_matrix.h:309
unsigned int total_nnz() const
Definition: sparse_matrix.h:297
An sparse matrix iterator class that tranverses row-wise.
Definition: sparse_matrix_iterator.inl:20
T at(unsigned int row, unsigned int col) const
Definition: sparse_matrix.inl:314
T * get_values()
Definition: sparse_matrix.h:315
starpu_data_handle_t registerSparseMatrix()
To register SparseMatrix with StarPU. Does not create partitions of Matrix.
Definition: sparse_matrix.h:418
SparseFileFormat
Can be used to specify the input format for a sparse matrix that is supplied in constructor.
Definition: sparse_matrix.h:37
Contains the definitions of member functions of the SparseMatrix class that are not related to any ba...
const T & operator()(const unsigned int row, const unsigned int col) const
Definition: sparse_matrix.inl:389