ViennaCL - The Vienna Computing Library  1.7.0
Free open-source GPU-accelerated linear algebra and solver library.
compressed_matrix.hpp
Go to the documentation of this file.
1 #ifndef VIENNACL_COMPRESSED_MATRIX_HPP_
2 #define VIENNACL_COMPRESSED_MATRIX_HPP_
3 
4 /* =========================================================================
5  Copyright (c) 2010-2015, Institute for Microelectronics,
6  Institute for Analysis and Scientific Computing,
7  TU Wien.
8  Portions of this software are copyright by UChicago Argonne, LLC.
9 
10  -----------------
11  ViennaCL - The Vienna Computing Library
12  -----------------
13 
14  Project Head: Karl Rupp rupp@iue.tuwien.ac.at
15 
16  (A list of authors and contributors can be found in the manual)
17 
18  License: MIT (X11), see file LICENSE in the base directory
19 ============================================================================= */
20 
25 #include <vector>
26 #include <list>
27 #include <map>
28 #include "viennacl/forwards.h"
29 #include "viennacl/vector.hpp"
30 
32 
33 #include "viennacl/tools/tools.hpp"
35 
36 #ifdef VIENNACL_WITH_UBLAS
37 #include <boost/numeric/ublas/matrix_sparse.hpp>
38 #endif
39 
40 namespace viennacl
41 {
42 namespace detail
43 {
44 
49  template<typename CPUMatrixT, typename NumericT, unsigned int AlignmentV>
50  void copy_impl(const CPUMatrixT & cpu_matrix,
52  vcl_size_t nonzeros)
53  {
54  assert( (gpu_matrix.size1() == 0 || viennacl::traits::size1(cpu_matrix) == gpu_matrix.size1()) && bool("Size mismatch") );
55  assert( (gpu_matrix.size2() == 0 || viennacl::traits::size2(cpu_matrix) == gpu_matrix.size2()) && bool("Size mismatch") );
56 
57  viennacl::backend::typesafe_host_array<unsigned int> row_buffer(gpu_matrix.handle1(), cpu_matrix.size1() + 1);
58  viennacl::backend::typesafe_host_array<unsigned int> col_buffer(gpu_matrix.handle2(), nonzeros);
59  std::vector<NumericT> elements(nonzeros);
60 
61  vcl_size_t row_index = 0;
62  vcl_size_t data_index = 0;
63 
64  for (typename CPUMatrixT::const_iterator1 row_it = cpu_matrix.begin1();
65  row_it != cpu_matrix.end1();
66  ++row_it)
67  {
68  row_buffer.set(row_index, data_index);
69  ++row_index;
70 
71  for (typename CPUMatrixT::const_iterator2 col_it = row_it.begin();
72  col_it != row_it.end();
73  ++col_it)
74  {
75  col_buffer.set(data_index, col_it.index2());
76  elements[data_index] = *col_it;
77  ++data_index;
78  }
79  data_index = viennacl::tools::align_to_multiple<vcl_size_t>(data_index, AlignmentV); //take care of alignment
80  }
81  row_buffer.set(row_index, data_index);
82 
83  gpu_matrix.set(row_buffer.get(),
84  col_buffer.get(),
85  &elements[0],
86  cpu_matrix.size1(),
87  cpu_matrix.size2(),
88  nonzeros);
89  }
90 }
91 
92 //
93 // host to device:
94 //
95 
96 //provide copy-operation:
111 template<typename CPUMatrixT, typename NumericT, unsigned int AlignmentV>
112 void copy(const CPUMatrixT & cpu_matrix,
114 {
115  if ( cpu_matrix.size1() > 0 && cpu_matrix.size2() > 0 )
116  {
117  //determine nonzeros:
118  vcl_size_t num_entries = 0;
119  for (typename CPUMatrixT::const_iterator1 row_it = cpu_matrix.begin1();
120  row_it != cpu_matrix.end1();
121  ++row_it)
122  {
123  vcl_size_t entries_per_row = 0;
124  for (typename CPUMatrixT::const_iterator2 col_it = row_it.begin();
125  col_it != row_it.end();
126  ++col_it)
127  {
128  ++entries_per_row;
129  }
130  num_entries += viennacl::tools::align_to_multiple<vcl_size_t>(entries_per_row, AlignmentV);
131  }
132 
133  if (num_entries == 0) //we copy an empty matrix
134  num_entries = 1;
135 
136  //set up matrix entries:
137  viennacl::detail::copy_impl(cpu_matrix, gpu_matrix, num_entries);
138  }
139 }
140 
141 
142 //adapted for std::vector< std::map < > > argument:
148 template<typename SizeT, typename NumericT, unsigned int AlignmentV>
149 void copy(const std::vector< std::map<SizeT, NumericT> > & cpu_matrix,
151 {
152  vcl_size_t nonzeros = 0;
153  vcl_size_t max_col = 0;
154  for (vcl_size_t i=0; i<cpu_matrix.size(); ++i)
155  {
156  if (cpu_matrix[i].size() > 0)
157  nonzeros += ((cpu_matrix[i].size() - 1) / AlignmentV + 1) * AlignmentV;
158  if (cpu_matrix[i].size() > 0)
159  max_col = std::max<vcl_size_t>(max_col, (cpu_matrix[i].rbegin())->first);
160  }
161 
162  viennacl::detail::copy_impl(tools::const_sparse_matrix_adapter<NumericT, SizeT>(cpu_matrix, cpu_matrix.size(), max_col + 1),
163  gpu_matrix,
164  nonzeros);
165 }
166 
167 #ifdef VIENNACL_WITH_UBLAS
168 
172 template<typename ScalarType, typename F, vcl_size_t IB, typename IA, typename TA>
173 void copy(const boost::numeric::ublas::compressed_matrix<ScalarType, F, IB, IA, TA> & ublas_matrix,
175 {
176  assert( (gpu_matrix.size1() == 0 || viennacl::traits::size1(ublas_matrix) == gpu_matrix.size1()) && bool("Size mismatch") );
177  assert( (gpu_matrix.size2() == 0 || viennacl::traits::size2(ublas_matrix) == gpu_matrix.size2()) && bool("Size mismatch") );
178 
179  //we just need to copy the CSR arrays:
180  viennacl::backend::typesafe_host_array<unsigned int> row_buffer(gpu_matrix.handle1(), ublas_matrix.size1() + 1);
181  for (vcl_size_t i=0; i<=ublas_matrix.size1(); ++i)
182  row_buffer.set(i, ublas_matrix.index1_data()[i]);
183 
184  viennacl::backend::typesafe_host_array<unsigned int> col_buffer(gpu_matrix.handle2(), ublas_matrix.nnz());
185  for (vcl_size_t i=0; i<ublas_matrix.nnz(); ++i)
186  col_buffer.set(i, ublas_matrix.index2_data()[i]);
187 
188  gpu_matrix.set(row_buffer.get(),
189  col_buffer.get(),
190  &(ublas_matrix.value_data()[0]),
191  ublas_matrix.size1(),
192  ublas_matrix.size2(),
193  ublas_matrix.nnz());
194 
195 }
196 #endif
197 
198 #ifdef VIENNACL_WITH_ARMADILLO
199 
204 template<typename NumericT, unsigned int AlignmentV>
205 void copy(arma::SpMat<NumericT> const & arma_matrix,
207 {
208  assert( (vcl_matrix.size1() == 0 || static_cast<vcl_size_t>(arma_matrix.n_rows) == vcl_matrix.size1()) && bool("Size mismatch") );
209  assert( (vcl_matrix.size2() == 0 || static_cast<vcl_size_t>(arma_matrix.n_cols) == vcl_matrix.size2()) && bool("Size mismatch") );
210 
211  viennacl::backend::typesafe_host_array<unsigned int> row_buffer(vcl_matrix.handle1(), arma_matrix.n_rows + 1);
212  viennacl::backend::typesafe_host_array<unsigned int> col_buffer(vcl_matrix.handle2(), arma_matrix.n_nonzero);
213  viennacl::backend::typesafe_host_array<NumericT > value_buffer(vcl_matrix.handle(), arma_matrix.n_nonzero);
214 
215  // Step 1: Count number of nonzeros in each row
216  for (vcl_size_t col=0; col < static_cast<vcl_size_t>(arma_matrix.n_cols); ++col)
217  {
218  vcl_size_t col_begin = static_cast<vcl_size_t>(arma_matrix.col_ptrs[col]);
219  vcl_size_t col_end = static_cast<vcl_size_t>(arma_matrix.col_ptrs[col+1]);
220  for (vcl_size_t i = col_begin; i < col_end; ++i)
221  {
222  unsigned int row = arma_matrix.row_indices[i];
223  row_buffer.set(row, row_buffer[row] + 1);
224  }
225  }
226 
227  // Step 2: Exclusive scan on row_buffer to obtain offsets
228  unsigned int offset = 0;
229  for (vcl_size_t i=0; i<row_buffer.size(); ++i)
230  {
231  unsigned int tmp = row_buffer[i];
232  row_buffer.set(i, offset);
233  offset += tmp;
234  }
235 
236  // Step 3: Fill data
237  std::vector<unsigned int> row_offsets(arma_matrix.n_rows);
238  for (vcl_size_t col=0; col < static_cast<vcl_size_t>(arma_matrix.n_cols); ++col)
239  {
240  vcl_size_t col_begin = static_cast<vcl_size_t>(arma_matrix.col_ptrs[col]);
241  vcl_size_t col_end = static_cast<vcl_size_t>(arma_matrix.col_ptrs[col+1]);
242  for (vcl_size_t i = col_begin; i < col_end; ++i)
243  {
244  unsigned int row = arma_matrix.row_indices[i];
245  col_buffer.set(row_buffer[row] + row_offsets[row], col);
246  value_buffer.set(row_buffer[row] + row_offsets[row], arma_matrix.values[i]);
247  row_offsets[row] += 1;
248  }
249  }
250 
251  vcl_matrix.set(row_buffer.get(), col_buffer.get(), reinterpret_cast<NumericT*>(value_buffer.get()),
252  arma_matrix.n_rows, arma_matrix.n_cols, arma_matrix.n_nonzero);
253 }
254 #endif
255 
256 #ifdef VIENNACL_WITH_EIGEN
257 
261 template<typename NumericT, int flags, unsigned int AlignmentV>
262 void copy(const Eigen::SparseMatrix<NumericT, flags> & eigen_matrix,
263  compressed_matrix<NumericT, AlignmentV> & gpu_matrix)
264 {
265  assert( (gpu_matrix.size1() == 0 || static_cast<vcl_size_t>(eigen_matrix.rows()) == gpu_matrix.size1()) && bool("Size mismatch") );
266  assert( (gpu_matrix.size2() == 0 || static_cast<vcl_size_t>(eigen_matrix.cols()) == gpu_matrix.size2()) && bool("Size mismatch") );
267 
268  std::vector< std::map<unsigned int, NumericT> > stl_matrix(eigen_matrix.rows());
269 
270  for (int k=0; k < eigen_matrix.outerSize(); ++k)
271  for (typename Eigen::SparseMatrix<NumericT, flags>::InnerIterator it(eigen_matrix, k); it; ++it)
272  stl_matrix[it.row()][it.col()] = it.value();
273 
274  copy(tools::const_sparse_matrix_adapter<NumericT>(stl_matrix, eigen_matrix.rows(), eigen_matrix.cols()), gpu_matrix);
275 }
276 #endif
277 
278 
279 #ifdef VIENNACL_WITH_MTL4
280 
284 template<typename NumericT, unsigned int AlignmentV>
285 void copy(const mtl::compressed2D<NumericT> & cpu_matrix,
286  compressed_matrix<NumericT, AlignmentV> & gpu_matrix)
287 {
288  assert( (gpu_matrix.size1() == 0 || static_cast<vcl_size_t>(cpu_matrix.num_rows()) == gpu_matrix.size1()) && bool("Size mismatch") );
289  assert( (gpu_matrix.size2() == 0 || static_cast<vcl_size_t>(cpu_matrix.num_cols()) == gpu_matrix.size2()) && bool("Size mismatch") );
290 
291  typedef mtl::compressed2D<NumericT> MatrixType;
292 
293  std::vector< std::map<unsigned int, NumericT> > stl_matrix(cpu_matrix.num_rows());
294 
295  using mtl::traits::range_generator;
297 
298  // Choose between row and column traversal
299  typedef typename min<range_generator<mtl::tag::row, MatrixType>,
300  range_generator<mtl::tag::col, MatrixType> >::type range_type;
301  range_type my_range;
302 
303  // Type of outer cursor
304  typedef typename range_type::type c_type;
305  // Type of inner cursor
306  typedef typename mtl::traits::range_generator<mtl::tag::nz, c_type>::type ic_type;
307 
308  // Define the property maps
309  typename mtl::traits::row<MatrixType>::type row(cpu_matrix);
310  typename mtl::traits::col<MatrixType>::type col(cpu_matrix);
311  typename mtl::traits::const_value<MatrixType>::type value(cpu_matrix);
312 
313  // Now iterate over the matrix
314  for (c_type cursor(my_range.begin(cpu_matrix)), cend(my_range.end(cpu_matrix)); cursor != cend; ++cursor)
315  for (ic_type icursor(mtl::begin<mtl::tag::nz>(cursor)), icend(mtl::end<mtl::tag::nz>(cursor)); icursor != icend; ++icursor)
316  stl_matrix[row(*icursor)][col(*icursor)] = value(*icursor);
317 
318  copy(tools::const_sparse_matrix_adapter<NumericT>(stl_matrix, cpu_matrix.num_rows(), cpu_matrix.num_cols()), gpu_matrix);
319 }
320 #endif
321 
322 
323 
324 
325 
326 
327 
328 //
329 // device to host:
330 //
340 template<typename CPUMatrixT, typename NumericT, unsigned int AlignmentV>
342  CPUMatrixT & cpu_matrix )
343 {
344  assert( (viennacl::traits::size1(cpu_matrix) == gpu_matrix.size1()) && bool("Size mismatch") );
345  assert( (viennacl::traits::size2(cpu_matrix) == gpu_matrix.size2()) && bool("Size mismatch") );
346 
347  if ( gpu_matrix.size1() > 0 && gpu_matrix.size2() > 0 )
348  {
349  //get raw data from memory:
350  viennacl::backend::typesafe_host_array<unsigned int> row_buffer(gpu_matrix.handle1(), cpu_matrix.size1() + 1);
351  viennacl::backend::typesafe_host_array<unsigned int> col_buffer(gpu_matrix.handle2(), gpu_matrix.nnz());
352  std::vector<NumericT> elements(gpu_matrix.nnz());
353 
354  //std::cout << "GPU->CPU, nonzeros: " << gpu_matrix.nnz() << std::endl;
355 
356  viennacl::backend::memory_read(gpu_matrix.handle1(), 0, row_buffer.raw_size(), row_buffer.get());
357  viennacl::backend::memory_read(gpu_matrix.handle2(), 0, col_buffer.raw_size(), col_buffer.get());
358  viennacl::backend::memory_read(gpu_matrix.handle(), 0, sizeof(NumericT)* gpu_matrix.nnz(), &(elements[0]));
359 
360  //fill the cpu_matrix:
361  vcl_size_t data_index = 0;
362  for (vcl_size_t row = 1; row <= gpu_matrix.size1(); ++row)
363  {
364  while (data_index < row_buffer[row])
365  {
366  if (col_buffer[data_index] >= gpu_matrix.size2())
367  {
368  std::cerr << "ViennaCL encountered invalid data at colbuffer[" << data_index << "]: " << col_buffer[data_index] << std::endl;
369  return;
370  }
371 
372  if (std::fabs(elements[data_index]) > static_cast<NumericT>(0))
373  cpu_matrix(row-1, static_cast<vcl_size_t>(col_buffer[data_index])) = elements[data_index];
374  ++data_index;
375  }
376  }
377  }
378 }
379 
380 
386 template<typename NumericT, unsigned int AlignmentV>
388  std::vector< std::map<unsigned int, NumericT> > & cpu_matrix)
389 {
390  assert( (cpu_matrix.size() == gpu_matrix.size1()) && bool("Size mismatch") );
391 
392  tools::sparse_matrix_adapter<NumericT> temp(cpu_matrix, gpu_matrix.size1(), gpu_matrix.size2());
393  copy(gpu_matrix, temp);
394 }
395 
396 #ifdef VIENNACL_WITH_UBLAS
397 
401 template<typename ScalarType, unsigned int AlignmentV, typename F, vcl_size_t IB, typename IA, typename TA>
403  boost::numeric::ublas::compressed_matrix<ScalarType> & ublas_matrix)
404 {
405  assert( (viennacl::traits::size1(ublas_matrix) == gpu_matrix.size1()) && bool("Size mismatch") );
406  assert( (viennacl::traits::size2(ublas_matrix) == gpu_matrix.size2()) && bool("Size mismatch") );
407 
408  viennacl::backend::typesafe_host_array<unsigned int> row_buffer(gpu_matrix.handle1(), gpu_matrix.size1() + 1);
409  viennacl::backend::typesafe_host_array<unsigned int> col_buffer(gpu_matrix.handle2(), gpu_matrix.nnz());
410 
411  viennacl::backend::memory_read(gpu_matrix.handle1(), 0, row_buffer.raw_size(), row_buffer.get());
412  viennacl::backend::memory_read(gpu_matrix.handle2(), 0, col_buffer.raw_size(), col_buffer.get());
413 
414  ublas_matrix.clear();
415  ublas_matrix.reserve(gpu_matrix.nnz());
416 
417  ublas_matrix.set_filled(gpu_matrix.size1() + 1, gpu_matrix.nnz());
418 
419  for (vcl_size_t i=0; i<ublas_matrix.size1() + 1; ++i)
420  ublas_matrix.index1_data()[i] = row_buffer[i];
421 
422  for (vcl_size_t i=0; i<ublas_matrix.nnz(); ++i)
423  ublas_matrix.index2_data()[i] = col_buffer[i];
424 
425  viennacl::backend::memory_read(gpu_matrix.handle(), 0, sizeof(ScalarType) * gpu_matrix.nnz(), &(ublas_matrix.value_data()[0]));
426 
427 }
428 #endif
429 
430 #ifdef VIENNACL_WITH_ARMADILLO
431 
436 template<typename NumericT, unsigned int AlignmentV>
438  arma::SpMat<NumericT> & arma_matrix)
439 {
440  assert( (static_cast<vcl_size_t>(arma_matrix.n_rows) == vcl_matrix.size1()) && bool("Size mismatch") );
441  assert( (static_cast<vcl_size_t>(arma_matrix.n_cols) == vcl_matrix.size2()) && bool("Size mismatch") );
442 
443  if ( vcl_matrix.size1() > 0 && vcl_matrix.size2() > 0 )
444  {
445  //get raw data from memory:
446  viennacl::backend::typesafe_host_array<unsigned int> row_buffer(vcl_matrix.handle1(), vcl_matrix.size1() + 1);
447  viennacl::backend::typesafe_host_array<unsigned int> col_buffer(vcl_matrix.handle2(), vcl_matrix.nnz());
448  viennacl::backend::typesafe_host_array<NumericT> elements (vcl_matrix.handle(), vcl_matrix.nnz());
449 
450  viennacl::backend::memory_read(vcl_matrix.handle1(), 0, row_buffer.raw_size(), row_buffer.get());
451  viennacl::backend::memory_read(vcl_matrix.handle2(), 0, col_buffer.raw_size(), col_buffer.get());
452  viennacl::backend::memory_read(vcl_matrix.handle(), 0, elements.raw_size(), elements.get());
453 
454  arma_matrix.zeros();
455  vcl_size_t data_index = 0;
456  for (vcl_size_t row = 1; row <= vcl_matrix.size1(); ++row)
457  {
458  while (data_index < row_buffer[row])
459  {
460  assert(col_buffer[data_index] < vcl_matrix.size2() && bool("ViennaCL encountered invalid data at col_buffer"));
461  if (elements[data_index] != static_cast<NumericT>(0.0))
462  arma_matrix(row-1, col_buffer[data_index]) = elements[data_index];
463  ++data_index;
464  }
465  }
466  }
467 }
468 #endif
469 
470 #ifdef VIENNACL_WITH_EIGEN
471 
472 template<typename NumericT, int flags, unsigned int AlignmentV>
473 void copy(compressed_matrix<NumericT, AlignmentV> & gpu_matrix,
474  Eigen::SparseMatrix<NumericT, flags> & eigen_matrix)
475 {
476  assert( (static_cast<vcl_size_t>(eigen_matrix.rows()) == gpu_matrix.size1()) && bool("Size mismatch") );
477  assert( (static_cast<vcl_size_t>(eigen_matrix.cols()) == gpu_matrix.size2()) && bool("Size mismatch") );
478 
479  if ( gpu_matrix.size1() > 0 && gpu_matrix.size2() > 0 )
480  {
481  //get raw data from memory:
482  viennacl::backend::typesafe_host_array<unsigned int> row_buffer(gpu_matrix.handle1(), gpu_matrix.size1() + 1);
483  viennacl::backend::typesafe_host_array<unsigned int> col_buffer(gpu_matrix.handle2(), gpu_matrix.nnz());
484  std::vector<NumericT> elements(gpu_matrix.nnz());
485 
486  viennacl::backend::memory_read(gpu_matrix.handle1(), 0, row_buffer.raw_size(), row_buffer.get());
487  viennacl::backend::memory_read(gpu_matrix.handle2(), 0, col_buffer.raw_size(), col_buffer.get());
488  viennacl::backend::memory_read(gpu_matrix.handle(), 0, sizeof(NumericT)* gpu_matrix.nnz(), &(elements[0]));
489 
490  eigen_matrix.setZero();
491  vcl_size_t data_index = 0;
492  for (vcl_size_t row = 1; row <= gpu_matrix.size1(); ++row)
493  {
494  while (data_index < row_buffer[row])
495  {
496  assert(col_buffer[data_index] < gpu_matrix.size2() && bool("ViennaCL encountered invalid data at col_buffer"));
497  if (elements[data_index] != static_cast<NumericT>(0.0))
498  eigen_matrix.insert(row-1, col_buffer[data_index]) = elements[data_index];
499  ++data_index;
500  }
501  }
502  }
503 }
504 #endif
505 
506 
507 
508 #ifdef VIENNACL_WITH_MTL4
509 
510 template<typename NumericT, unsigned int AlignmentV>
511 void copy(compressed_matrix<NumericT, AlignmentV> & gpu_matrix,
512  mtl::compressed2D<NumericT> & mtl4_matrix)
513 {
514  assert( (static_cast<vcl_size_t>(mtl4_matrix.num_rows()) == gpu_matrix.size1()) && bool("Size mismatch") );
515  assert( (static_cast<vcl_size_t>(mtl4_matrix.num_cols()) == gpu_matrix.size2()) && bool("Size mismatch") );
516 
517  if ( gpu_matrix.size1() > 0 && gpu_matrix.size2() > 0 )
518  {
519 
520  //get raw data from memory:
521  viennacl::backend::typesafe_host_array<unsigned int> row_buffer(gpu_matrix.handle1(), gpu_matrix.size1() + 1);
522  viennacl::backend::typesafe_host_array<unsigned int> col_buffer(gpu_matrix.handle2(), gpu_matrix.nnz());
523  std::vector<NumericT> elements(gpu_matrix.nnz());
524 
525  viennacl::backend::memory_read(gpu_matrix.handle1(), 0, row_buffer.raw_size(), row_buffer.get());
526  viennacl::backend::memory_read(gpu_matrix.handle2(), 0, col_buffer.raw_size(), col_buffer.get());
527  viennacl::backend::memory_read(gpu_matrix.handle(), 0, sizeof(NumericT)* gpu_matrix.nnz(), &(elements[0]));
528 
529  //set_to_zero(mtl4_matrix);
530  //mtl4_matrix.change_dim(gpu_matrix.size1(), gpu_matrix.size2());
531 
532  mtl::matrix::inserter< mtl::compressed2D<NumericT> > ins(mtl4_matrix);
533  vcl_size_t data_index = 0;
534  for (vcl_size_t row = 1; row <= gpu_matrix.size1(); ++row)
535  {
536  while (data_index < row_buffer[row])
537  {
538  assert(col_buffer[data_index] < gpu_matrix.size2() && bool("ViennaCL encountered invalid data at col_buffer"));
539  if (elements[data_index] != static_cast<NumericT>(0.0))
540  ins(row-1, col_buffer[data_index]) << typename mtl::Collection< mtl::compressed2D<NumericT> >::value_type(elements[data_index]);
541  ++data_index;
542  }
543  }
544  }
545 }
546 #endif
547 
548 
549 
550 
551 
553 
558 template<class NumericT, unsigned int AlignmentV /* see VCLForwards.h */>
560 {
561 public:
565 
567  compressed_matrix() : rows_(0), cols_(0), nonzeros_(0), row_block_num_(0) {}
568 
577  : rows_(rows), cols_(cols), nonzeros_(nonzeros), row_block_num_(0)
578  {
579  row_buffer_.switch_active_handle_id(ctx.memory_type());
580  col_buffer_.switch_active_handle_id(ctx.memory_type());
581  elements_.switch_active_handle_id(ctx.memory_type());
582  row_blocks_.switch_active_handle_id(ctx.memory_type());
583 
584 #ifdef VIENNACL_WITH_OPENCL
585  if (ctx.memory_type() == OPENCL_MEMORY)
586  {
587  row_buffer_.opencl_handle().context(ctx.opencl_context());
588  col_buffer_.opencl_handle().context(ctx.opencl_context());
589  elements_.opencl_handle().context(ctx.opencl_context());
590  row_blocks_.opencl_handle().context(ctx.opencl_context());
591  }
592 #endif
593  if (rows > 0)
594  {
596  }
597  if (nonzeros > 0)
598  {
600  viennacl::backend::memory_create(elements_, sizeof(NumericT) * nonzeros, ctx);
601  }
602  }
603 
611  : rows_(rows), cols_(cols), nonzeros_(0), row_block_num_(0)
612  {
613  row_buffer_.switch_active_handle_id(ctx.memory_type());
614  col_buffer_.switch_active_handle_id(ctx.memory_type());
615  elements_.switch_active_handle_id(ctx.memory_type());
616  row_blocks_.switch_active_handle_id(ctx.memory_type());
617 
618 #ifdef VIENNACL_WITH_OPENCL
619  if (ctx.memory_type() == OPENCL_MEMORY)
620  {
621  row_buffer_.opencl_handle().context(ctx.opencl_context());
622  col_buffer_.opencl_handle().context(ctx.opencl_context());
623  elements_.opencl_handle().context(ctx.opencl_context());
624  row_blocks_.opencl_handle().context(ctx.opencl_context());
625  }
626 #endif
627  if (rows > 0)
628  {
630  }
631  }
632 
637  explicit compressed_matrix(viennacl::context ctx) : rows_(0), cols_(0), nonzeros_(0), row_block_num_(0)
638  {
639  row_buffer_.switch_active_handle_id(ctx.memory_type());
640  col_buffer_.switch_active_handle_id(ctx.memory_type());
641  elements_.switch_active_handle_id(ctx.memory_type());
642  row_blocks_.switch_active_handle_id(ctx.memory_type());
643 
644 #ifdef VIENNACL_WITH_OPENCL
645  if (ctx.memory_type() == OPENCL_MEMORY)
646  {
647  row_buffer_.opencl_handle().context(ctx.opencl_context());
648  col_buffer_.opencl_handle().context(ctx.opencl_context());
649  elements_.opencl_handle().context(ctx.opencl_context());
650  row_blocks_.opencl_handle().context(ctx.opencl_context());
651  }
652 #endif
653  }
654 
655 
656 #ifdef VIENNACL_WITH_OPENCL
657 
666  explicit compressed_matrix(cl_mem mem_row_buffer, cl_mem mem_col_buffer, cl_mem mem_elements,
667  vcl_size_t rows, vcl_size_t cols, vcl_size_t nonzeros) :
668  rows_(rows), cols_(cols), nonzeros_(nonzeros), row_block_num_(0)
669  {
671  row_buffer_.opencl_handle() = mem_row_buffer;
672  row_buffer_.opencl_handle().inc(); //prevents that the user-provided memory is deleted once the matrix object is destroyed.
673  row_buffer_.raw_size(sizeof(cl_uint) * (rows + 1));
674 
676  col_buffer_.opencl_handle() = mem_col_buffer;
677  col_buffer_.opencl_handle().inc(); //prevents that the user-provided memory is deleted once the matrix object is destroyed.
678  col_buffer_.raw_size(sizeof(cl_uint) * nonzeros);
679 
681  elements_.opencl_handle() = mem_elements;
682  elements_.opencl_handle().inc(); //prevents that the user-provided memory is deleted once the matrix object is destroyed.
683  elements_.raw_size(sizeof(NumericT) * nonzeros);
684 
685  //generate block information for CSR-adaptive:
687  }
688 #endif
689 
692  : rows_(0), cols_(0), nonzeros_(0), row_block_num_(0)
693  {
695 
696  row_buffer_.switch_active_handle_id(ctx.memory_type());
697  col_buffer_.switch_active_handle_id(ctx.memory_type());
698  elements_.switch_active_handle_id(ctx.memory_type());
699  row_blocks_.switch_active_handle_id(ctx.memory_type());
700 
701 #ifdef VIENNACL_WITH_OPENCL
702  if (ctx.memory_type() == OPENCL_MEMORY)
703  {
704  row_buffer_.opencl_handle().context(ctx.opencl_context());
705  col_buffer_.opencl_handle().context(ctx.opencl_context());
706  elements_.opencl_handle().context(ctx.opencl_context());
707  row_blocks_.opencl_handle().context(ctx.opencl_context());
708  }
709 #endif
710 
711  viennacl::linalg::prod_impl(proxy.lhs(), proxy.rhs(), *this);
713  }
714 
717  {
718  assert( (rows_ == 0 || rows_ == other.size1()) && bool("Size mismatch") );
719  assert( (cols_ == 0 || cols_ == other.size2()) && bool("Size mismatch") );
720 
721  rows_ = other.size1();
722  cols_ = other.size2();
723  nonzeros_ = other.nnz();
724  row_block_num_ = other.row_block_num_;
725 
726  viennacl::backend::typesafe_memory_copy<unsigned int>(other.row_buffer_, row_buffer_);
727  viennacl::backend::typesafe_memory_copy<unsigned int>(other.col_buffer_, col_buffer_);
728  viennacl::backend::typesafe_memory_copy<unsigned int>(other.row_blocks_, row_blocks_);
729  viennacl::backend::typesafe_memory_copy<NumericT>(other.elements_, elements_);
730 
731  return *this;
732  }
733 
736  {
737  assert( (rows_ == 0 || rows_ == proxy.lhs().size1()) && bool("Size mismatch") );
738  assert( (cols_ == 0 || cols_ == proxy.rhs().size2()) && bool("Size mismatch") );
739 
740  viennacl::linalg::prod_impl(proxy.lhs(), proxy.rhs(), *this);
742 
743  return *this;
744  }
745 
746 
760  void set(const void * row_jumper,
761  const void * col_buffer,
762  const NumericT * elements,
763  vcl_size_t rows,
764  vcl_size_t cols,
765  vcl_size_t nonzeros)
766  {
767  assert( (rows > 0) && bool("Error in compressed_matrix::set(): Number of rows must be larger than zero!"));
768  assert( (cols > 0) && bool("Error in compressed_matrix::set(): Number of columns must be larger than zero!"));
769  assert( (nonzeros > 0) && bool("Error in compressed_matrix::set(): Number of nonzeros must be larger than zero!"));
770  //std::cout << "Setting memory: " << cols + 1 << ", " << nonzeros << std::endl;
771 
772  //row_buffer_.switch_active_handle_id(viennacl::backend::OPENCL_MEMORY);
774 
775  //col_buffer_.switch_active_handle_id(viennacl::backend::OPENCL_MEMORY);
777 
778  //elements_.switch_active_handle_id(viennacl::backend::OPENCL_MEMORY);
779  viennacl::backend::memory_create(elements_, sizeof(NumericT) * nonzeros, viennacl::traits::context(elements_), elements);
780 
781  nonzeros_ = nonzeros;
782  rows_ = rows;
783  cols_ = cols;
784 
785  //generate block information for CSR-adaptive:
787  }
788 
790  void reserve(vcl_size_t new_nonzeros, bool preserve = true)
791  {
792  if (new_nonzeros > nonzeros_)
793  {
794  if (preserve)
795  {
796  handle_type col_buffer_old;
797  handle_type elements_old;
798  viennacl::backend::memory_shallow_copy(col_buffer_, col_buffer_old);
799  viennacl::backend::memory_shallow_copy(elements_, elements_old);
800 
802  viennacl::backend::memory_create(col_buffer_, size_deducer.element_size() * new_nonzeros, viennacl::traits::context(col_buffer_));
803  viennacl::backend::memory_create(elements_, sizeof(NumericT) * new_nonzeros, viennacl::traits::context(elements_));
804 
805  viennacl::backend::memory_copy(col_buffer_old, col_buffer_, 0, 0, size_deducer.element_size() * nonzeros_);
806  viennacl::backend::memory_copy(elements_old, elements_, 0, 0, sizeof(NumericT)* nonzeros_);
807  }
808  else
809  {
811  viennacl::backend::memory_create(col_buffer_, size_deducer.element_size() * new_nonzeros, viennacl::traits::context(col_buffer_));
812  viennacl::backend::memory_create(elements_, sizeof(NumericT) * new_nonzeros, viennacl::traits::context(elements_));
813  }
814 
815  nonzeros_ = new_nonzeros;
816  }
817  }
818 
825  void resize(vcl_size_t new_size1, vcl_size_t new_size2, bool preserve = true)
826  {
827  assert(new_size1 > 0 && new_size2 > 0 && bool("Cannot resize to zero size!"));
828 
829  if (new_size1 != rows_ || new_size2 != cols_)
830  {
831  if (!preserve)
832  {
833  viennacl::backend::typesafe_host_array<unsigned int> host_row_buffer(row_buffer_, new_size1 + 1);
835  // faster version without initializing memory:
836  //viennacl::backend::memory_create(row_buffer_, viennacl::backend::typesafe_host_array<unsigned int>().element_size() * (new_size1 + 1), viennacl::traits::context(row_buffer_));
837  nonzeros_ = 0;
838  }
839  else
840  {
841  std::vector<std::map<unsigned int, NumericT> > stl_sparse_matrix;
842  if (rows_ > 0)
843  {
844  stl_sparse_matrix.resize(rows_);
845  viennacl::copy(*this, stl_sparse_matrix);
846  } else {
847  stl_sparse_matrix.resize(new_size1);
848  stl_sparse_matrix[0][0] = 0; //enforces nonzero array sizes if matrix was initially empty
849  }
850 
851  stl_sparse_matrix.resize(new_size1);
852 
853  //discard entries with column index larger than new_size2
854  if (new_size2 < cols_ && rows_ > 0)
855  {
856  for (vcl_size_t i=0; i<stl_sparse_matrix.size(); ++i)
857  {
858  std::list<unsigned int> to_delete;
859  for (typename std::map<unsigned int, NumericT>::iterator it = stl_sparse_matrix[i].begin();
860  it != stl_sparse_matrix[i].end();
861  ++it)
862  {
863  if (it->first >= new_size2)
864  to_delete.push_back(it->first);
865  }
866 
867  for (std::list<unsigned int>::iterator it = to_delete.begin(); it != to_delete.end(); ++it)
868  stl_sparse_matrix[i].erase(*it);
869  }
870  }
871 
872  viennacl::copy(stl_sparse_matrix, *this);
873  }
874 
875  rows_ = new_size1;
876  cols_ = new_size2;
877  }
878  }
879 
881  void clear()
882  {
883  viennacl::backend::typesafe_host_array<unsigned int> host_row_buffer(row_buffer_, rows_ + 1);
884  viennacl::backend::typesafe_host_array<unsigned int> host_col_buffer(col_buffer_, 1);
885  std::vector<NumericT> host_elements(1);
886 
887  viennacl::backend::memory_create(row_buffer_, host_row_buffer.element_size() * (rows_ + 1), viennacl::traits::context(row_buffer_), host_row_buffer.get());
888  viennacl::backend::memory_create(col_buffer_, host_col_buffer.element_size() * 1, viennacl::traits::context(col_buffer_), host_col_buffer.get());
889  viennacl::backend::memory_create(elements_, sizeof(NumericT) * 1, viennacl::traits::context(elements_), &(host_elements[0]));
890 
891  nonzeros_ = 0;
892  }
893 
896  {
897  assert( (i < rows_) && (j < cols_) && bool("compressed_matrix access out of bounds!"));
898 
899  vcl_size_t index = element_index(i, j);
900 
901  // check for element in sparsity pattern
902  if (index < nonzeros_)
903  return entry_proxy<NumericT>(index, elements_);
904 
905  // Element not found. Copying required. Very slow, but direct entry manipulation is painful anyway...
906  std::vector< std::map<unsigned int, NumericT> > cpu_backup(rows_);
907  tools::sparse_matrix_adapter<NumericT> adapted_cpu_backup(cpu_backup, rows_, cols_);
908  viennacl::copy(*this, adapted_cpu_backup);
909  cpu_backup[i][static_cast<unsigned int>(j)] = 0.0;
910  viennacl::copy(adapted_cpu_backup, *this);
911 
912  index = element_index(i, j);
913 
914  assert(index < nonzeros_);
915 
916  return entry_proxy<NumericT>(index, elements_);
917  }
918 
920  const vcl_size_t & size1() const { return rows_; }
922  const vcl_size_t & size2() const { return cols_; }
924  const vcl_size_t & nnz() const { return nonzeros_; }
926  const vcl_size_t & blocks1() const { return row_block_num_; }
927 
929  const handle_type & handle1() const { return row_buffer_; }
931  const handle_type & handle2() const { return col_buffer_; }
933  const handle_type & handle3() const { return row_blocks_; }
935  const handle_type & handle() const { return elements_; }
936 
938  handle_type & handle1() { return row_buffer_; }
940  handle_type & handle2() { return col_buffer_; }
942  handle_type & handle3() { return row_blocks_; }
944  handle_type & handle() { return elements_; }
945 
951  {
952  viennacl::backend::switch_memory_context<unsigned int>(row_buffer_, new_ctx);
953  viennacl::backend::switch_memory_context<unsigned int>(col_buffer_, new_ctx);
954  viennacl::backend::switch_memory_context<unsigned int>(row_blocks_, new_ctx);
955  viennacl::backend::switch_memory_context<NumericT>(elements_, new_ctx);
956  }
957 
960  {
961  return row_buffer_.get_active_handle_id();
962  }
963 
964 private:
965 
967  vcl_size_t element_index(vcl_size_t i, vcl_size_t j)
968  {
969  //read row indices
970  viennacl::backend::typesafe_host_array<unsigned int> row_indices(row_buffer_, 2);
971  viennacl::backend::memory_read(row_buffer_, row_indices.element_size()*i, row_indices.element_size()*2, row_indices.get());
972 
973  //get column indices for row i:
974  viennacl::backend::typesafe_host_array<unsigned int> col_indices(col_buffer_, row_indices[1] - row_indices[0]);
975  viennacl::backend::memory_read(col_buffer_, col_indices.element_size()*row_indices[0], row_indices.element_size()*col_indices.size(), col_indices.get());
976 
977  for (vcl_size_t k=0; k<col_indices.size(); ++k)
978  {
979  if (col_indices[k] == j)
980  return row_indices[0] + k;
981  }
982 
983  // if not found, return index past the end of the matrix (cf. matrix.end() in the spirit of the STL)
984  return nonzeros_;
985  }
986 
987 public:
993  {
994  viennacl::backend::typesafe_host_array<unsigned int> row_buffer(row_buffer_, rows_ + 1);
995  viennacl::backend::memory_read(row_buffer_, 0, row_buffer.raw_size(), row_buffer.get());
996 
997  viennacl::backend::typesafe_host_array<unsigned int> row_blocks(row_buffer_, rows_ + 1);
998 
999  vcl_size_t num_entries_in_current_batch = 0;
1000 
1001  const vcl_size_t shared_mem_size = 1024; // number of column indices loaded to shared memory, number of floating point values loaded to shared memory
1002 
1003  row_block_num_ = 0;
1004  row_blocks.set(0, 0);
1005  for (vcl_size_t i=0; i<rows_; ++i)
1006  {
1007  vcl_size_t entries_in_row = vcl_size_t(row_buffer[i+1]) - vcl_size_t(row_buffer[i]);
1008  num_entries_in_current_batch += entries_in_row;
1009 
1010  if (num_entries_in_current_batch > shared_mem_size)
1011  {
1012  vcl_size_t rows_in_batch = i - row_blocks[row_block_num_];
1013  if (rows_in_batch > 0) // at least one full row is in the batch. Use current row in next batch.
1014  row_blocks.set(++row_block_num_, i--);
1015  else // row is larger than buffer in shared memory
1016  row_blocks.set(++row_block_num_, i+1);
1017  num_entries_in_current_batch = 0;
1018  }
1019  }
1020  if (num_entries_in_current_batch > 0)
1021  row_blocks.set(++row_block_num_, rows_);
1022 
1023  if (row_block_num_ > 0) //matrix might be empty...
1025  row_blocks.element_size() * (row_block_num_ + 1),
1026  viennacl::traits::context(row_buffer_), row_blocks.get());
1027 
1028  }
1029 
1030 private:
1031  // /** @brief Copy constructor is by now not available. */
1032  //compressed_matrix(compressed_matrix const &);
1033 
1034 private:
1035 
1036  vcl_size_t rows_;
1037  vcl_size_t cols_;
1038  vcl_size_t nonzeros_;
1039  vcl_size_t row_block_num_;
1040  handle_type row_buffer_;
1041  handle_type row_blocks_;
1042  handle_type col_buffer_;
1043  handle_type elements_;
1044 };
1045 
1051 template<typename NumericT, unsigned int AlignmentV>
1052 std::ostream & operator<<(std::ostream & os, compressed_matrix<NumericT, AlignmentV> const & A)
1053 {
1054  std::vector<std::map<unsigned int, NumericT> > tmp(A.size1());
1055  viennacl::copy(A, tmp);
1056  os << "compressed_matrix of size (" << A.size1() << ", " << A.size2() << ") with " << A.nnz() << " nonzeros:" << std::endl;
1057 
1058  for (vcl_size_t i=0; i<A.size1(); ++i)
1059  {
1060  for (typename std::map<unsigned int, NumericT>::const_iterator it = tmp[i].begin(); it != tmp[i].end(); ++it)
1061  os << " (" << i << ", " << it->first << ")\t" << it->second << std::endl;
1062  }
1063  return os;
1064 }
1065 
1066 //
1067 // Specify available operations:
1068 //
1069 
1072 namespace linalg
1073 {
1074 namespace detail
1075 {
1076  // x = A * y
1077  template<typename T, unsigned int A>
1078  struct op_executor<vector_base<T>, op_assign, vector_expression<const compressed_matrix<T, A>, const vector_base<T>, op_prod> >
1079  {
1080  static void apply(vector_base<T> & lhs, vector_expression<const compressed_matrix<T, A>, const vector_base<T>, op_prod> const & rhs)
1081  {
1082  // check for the special case x = A * x
1083  if (viennacl::traits::handle(lhs) == viennacl::traits::handle(rhs.rhs()))
1084  {
1085  viennacl::vector<T> temp(lhs);
1086  viennacl::linalg::prod_impl(rhs.lhs(), rhs.rhs(), temp);
1087  lhs = temp;
1088  }
1089  else
1090  viennacl::linalg::prod_impl(rhs.lhs(), rhs.rhs(), lhs);
1091  }
1092  };
1093 
1094  template<typename T, unsigned int A>
1095  struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const compressed_matrix<T, A>, const vector_base<T>, op_prod> >
1096  {
1097  static void apply(vector_base<T> & lhs, vector_expression<const compressed_matrix<T, A>, const vector_base<T>, op_prod> const & rhs)
1098  {
1099  viennacl::vector<T> temp(lhs);
1100  viennacl::linalg::prod_impl(rhs.lhs(), rhs.rhs(), temp);
1101  lhs += temp;
1102  }
1103  };
1104 
1105  template<typename T, unsigned int A>
1106  struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const compressed_matrix<T, A>, const vector_base<T>, op_prod> >
1107  {
1108  static void apply(vector_base<T> & lhs, vector_expression<const compressed_matrix<T, A>, const vector_base<T>, op_prod> const & rhs)
1109  {
1110  viennacl::vector<T> temp(lhs);
1111  viennacl::linalg::prod_impl(rhs.lhs(), rhs.rhs(), temp);
1112  lhs -= temp;
1113  }
1114  };
1115 
1116 
1117  // x = A * vec_op
1118  template<typename T, unsigned int A, typename LHS, typename RHS, typename OP>
1119  struct op_executor<vector_base<T>, op_assign, vector_expression<const compressed_matrix<T, A>, const vector_expression<const LHS, const RHS, OP>, op_prod> >
1120  {
1121  static void apply(vector_base<T> & lhs, vector_expression<const compressed_matrix<T, A>, const vector_expression<const LHS, const RHS, OP>, op_prod> const & rhs)
1122  {
1123  viennacl::vector<T> temp(rhs.rhs(), viennacl::traits::context(rhs));
1124  viennacl::linalg::prod_impl(rhs.lhs(), temp, lhs);
1125  }
1126  };
1127 
1128  // x = A * vec_op
1129  template<typename T, unsigned int A, typename LHS, typename RHS, typename OP>
1130  struct op_executor<vector_base<T>, op_inplace_add, vector_expression<const compressed_matrix<T, A>, vector_expression<const LHS, const RHS, OP>, op_prod> >
1131  {
1132  static void apply(vector_base<T> & lhs, vector_expression<const compressed_matrix<T, A>, vector_expression<const LHS, const RHS, OP>, op_prod> const & rhs)
1133  {
1134  viennacl::vector<T> temp(rhs.rhs(), viennacl::traits::context(rhs));
1135  viennacl::vector<T> temp_result(lhs);
1136  viennacl::linalg::prod_impl(rhs.lhs(), temp, temp_result);
1137  lhs += temp_result;
1138  }
1139  };
1140 
1141  // x = A * vec_op
1142  template<typename T, unsigned int A, typename LHS, typename RHS, typename OP>
1143  struct op_executor<vector_base<T>, op_inplace_sub, vector_expression<const compressed_matrix<T, A>, const vector_expression<const LHS, const RHS, OP>, op_prod> >
1144  {
1145  static void apply(vector_base<T> & lhs, vector_expression<const compressed_matrix<T, A>, const vector_expression<const LHS, const RHS, OP>, op_prod> const & rhs)
1146  {
1147  viennacl::vector<T> temp(rhs.rhs(), viennacl::traits::context(rhs));
1148  viennacl::vector<T> temp_result(lhs);
1149  viennacl::linalg::prod_impl(rhs.lhs(), temp, temp_result);
1150  lhs -= temp_result;
1151  }
1152  };
1153 
1154 } // namespace detail
1155 } // namespace linalg
1157 }
1158 
1159 #endif
const vcl_size_t & size2() const
Returns the number of columns.
Helper class implementing an array on the host. Default case: No conversion necessary.
Definition: util.hpp:92
vcl_size_t element_size() const
Definition: util.hpp:112
This class represents a single scalar value on the GPU and behaves mostly like a built-in scalar type...
Definition: forwards.h:227
const vcl_size_t & size1() const
Returns the number of rows.
Various little tools used here and there in ViennaCL.
void switch_memory_context(viennacl::context new_ctx)
Switches the memory context of the matrix.
vcl_size_t size1(MatrixType const &mat)
Generic routine for obtaining the number of rows of a matrix (ViennaCL, uBLAS, etc.)
Definition: size.hpp:163
A proxy class for entries in a vector.
Expression template class for representing a tree of expressions which ultimately result in a matrix...
Definition: forwards.h:341
This file provides the forward declarations for the main types used within ViennaCL.
void memory_read(mem_handle const &src_buffer, vcl_size_t src_offset, vcl_size_t bytes_to_read, void *ptr, bool async=false)
Reads data from a buffer back to main RAM.
Definition: memory.hpp:261
result_of::size_type< MatrixType >::type size2(MatrixType const &mat)
Generic routine for obtaining the number of columns of a matrix (ViennaCL, uBLAS, etc...
Definition: size.hpp:201
const handle_type & handle() const
Returns the OpenCL handle to the matrix entry array.
const handle_type & handle1() const
Returns the OpenCL handle to the row index array.
const vcl_size_t & nnz() const
Returns the number of nonzero entries.
vcl_size_t element_size(memory_types)
Definition: memory.hpp:299
float NumericT
Definition: bisect.cpp:40
Represents a generic 'context' similar to an OpenCL context, but is backend-agnostic and thus also su...
Definition: context.hpp:39
Main namespace in ViennaCL. Holds all the basic types such as vector, matrix, etc. and defines operations upon them.
Definition: cpu_ram.hpp:34
void generate_row_block_information()
Builds the row block information needed for fast sparse matrix-vector multiplications.
vcl_size_t size(VectorType const &vec)
Generic routine for obtaining the size of a vector (ViennaCL, uBLAS, etc.)
Definition: size.hpp:235
entry_proxy< NumericT > operator()(vcl_size_t i, vcl_size_t j)
Returns a reference to the (i,j)-th entry of the sparse matrix. If (i,j) does not exist (zero)...
handle_type & handle3()
Returns the OpenCL handle to the row block array.
Definition: blas3.hpp:36
handle_type & handle()
Returns the OpenCL handle to the matrix entry array.
Implementations of operations using sparse matrices.
const handle_type & handle2() const
Returns the OpenCL handle to the column index array.
void clear()
Resets all entries in the matrix back to zero without changing the matrix size. Resets the sparsity p...
Adapts a constant sparse matrix type made up from std::vector > to basic ub...
Definition: adapter.hpp:183
scalar< typename viennacl::tools::CHECK_SCALAR_TEMPLATE_ARGUMENT< NumericT >::ResultType > value_type
std::size_t vcl_size_t
Definition: forwards.h:75
compressed_matrix(vcl_size_t rows, vcl_size_t cols, viennacl::context ctx)
Construction of a compressed matrix with the supplied number of rows and columns. If the number of no...
vector_expression< const matrix_base< NumericT, F >, const unsigned int, op_row > row(const matrix_base< NumericT, F > &A, unsigned int i)
Definition: matrix.hpp:900
viennacl::memory_types memory_type() const
Definition: context.hpp:76
void copy_impl(const CPUMatrixT &cpu_matrix, compressed_compressed_matrix< NumericT > &gpu_matrix, vcl_size_t nonzero_rows, vcl_size_t nonzeros)
viennacl::memory_types memory_context() const
Returns the current memory context to determine whether the matrix is set up for OpenMP, OpenCL, or CUDA.
RHS & rhs() const
Get right hand side operand.
Definition: matrix.hpp:69
void reserve(vcl_size_t new_nonzeros, bool preserve=true)
Allocate memory for the supplied number of nonzeros in the matrix. Old values are preserved...
const handle_type & handle3() const
Returns the OpenCL handle to the row block array.
handle_type & handle1()
Returns the OpenCL handle to the row index array.
compressed_matrix(vcl_size_t rows, vcl_size_t cols, vcl_size_t nonzeros=0, viennacl::context ctx=viennacl::context())
Construction of a compressed matrix with the supplied number of rows and columns. If the number of no...
void switch_active_handle_id(memory_types new_id)
Switches the currently active handle. If no support for that backend is provided, an exception is thr...
Definition: mem_handle.hpp:121
void memory_copy(mem_handle const &src_buffer, mem_handle &dst_buffer, vcl_size_t src_offset, vcl_size_t dst_offset, vcl_size_t bytes_to_copy)
Copies 'bytes_to_copy' bytes from address 'src_buffer + src_offset' to memory starting at address 'ds...
Definition: memory.hpp:140
compressed_matrix(viennacl::context ctx)
Creates an empty compressed_matrix, but sets the respective context information.
viennacl::context context(T const &t)
Returns an ID for the currently active memory domain of an object.
Definition: context.hpp:40
The vector type with operator-overloads and proxy classes is defined here. Linear algebra operations ...
void copy(std::vector< NumericT > &cpu_vec, circulant_matrix< NumericT, AlignmentV > &gpu_mat)
Copies a circulant matrix from the std::vector to the OpenCL device (either GPU or multi-core CPU) ...
void set(const void *row_jumper, const void *col_buffer, const NumericT *elements, vcl_size_t rows, vcl_size_t cols, vcl_size_t nonzeros)
Sets the row, column and value arrays of the compressed matrix.
void set(vcl_size_t index, U value)
Definition: util.hpp:115
viennacl::backend::mem_handle handle_type
float ScalarType
Definition: fft_1d.cpp:42
Main abstraction class for multiple memory domains. Represents a buffer in either main RAM...
Definition: mem_handle.hpp:89
vcl_size_t raw_size() const
Returns the number of bytes of the currently active buffer.
Definition: mem_handle.hpp:230
Adapts a non-const sparse matrix type made up from std::vector > to basic u...
Definition: adapter.hpp:357
A sparse square matrix in compressed sparse rows format.
void memory_create(mem_handle &handle, vcl_size_t size_in_bytes, viennacl::context const &ctx, const void *host_ptr=NULL)
Creates an array of the specified size. If the second argument is provided, the buffer is initialized...
Definition: memory.hpp:87
T min(const T &lhs, const T &rhs)
Minimum.
Definition: util.hpp:45
void prod_impl(const matrix_base< NumericT > &mat, const vector_base< NumericT > &vec, vector_base< NumericT > &result)
Carries out matrix-vector multiplication.
compressed_matrix(matrix_expression< const compressed_matrix, const compressed_matrix, op_prod > const &proxy)
Assignment a compressed matrix from the product of two compressed_matrix objects (C = A * B)...
viennacl::backend::mem_handle & handle(T &obj)
Returns the generic memory handle of an object. Non-const version.
Definition: handle.hpp:41
memory_types
Definition: forwards.h:345
LHS & lhs() const
Get left hand side operand.
Definition: matrix.hpp:66
vcl_size_t raw_size() const
Definition: util.hpp:111
const vcl_size_t & blocks1() const
Returns the internal number of row blocks for an adaptive SpMV.
A proxy class for a single element of a vector or matrix. This proxy should not be noticed by end-use...
Definition: forwards.h:233
compressed_matrix()
Default construction of a compressed matrix. No memory is allocated.
void resize(vcl_size_t new_size1, vcl_size_t new_size2, bool preserve=true)
Resize the matrix.
void memory_shallow_copy(mem_handle const &src_buffer, mem_handle &dst_buffer)
A 'shallow' copy operation from an initialized buffer to an uninitialized buffer. The uninitialized b...
Definition: memory.hpp:177
compressed_matrix & operator=(compressed_matrix const &other)
Assignment a compressed matrix from possibly another memory domain.
handle_type & handle2()
Returns the OpenCL handle to the column index array.
compressed_matrix & operator=(matrix_expression< const compressed_matrix, const compressed_matrix, op_prod > const &proxy)
Assignment a compressed matrix from the product of two compressed_matrix objects (C = A * B)...
memory_types get_active_handle_id() const
Returns an ID for the currently active memory buffer. Other memory buffers might contain old or no da...
Definition: mem_handle.hpp:118