ViennaCL - The Vienna Computing Library  1.7.1
Free open-source GPU-accelerated linear algebra and solver library.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
scheduler_sparse.cpp
Go to the documentation of this file.
1 /* =========================================================================
2  Copyright (c) 2010-2016, Institute for Microelectronics,
3  Institute for Analysis and Scientific Computing,
4  TU Wien.
5  Portions of this software are copyright by UChicago Argonne, LLC.
6 
7  -----------------
8  ViennaCL - The Vienna Computing Library
9  -----------------
10 
11  Project Head: Karl Rupp rupp@iue.tuwien.ac.at
12 
13  (A list of authors and contributors can be found in the PDF manual)
14 
15  License: MIT (X11), see file LICENSE in the base directory
16 ============================================================================= */
17 
18 
23 //
24 // *** System
25 //
26 #include <iostream>
27 
28 //
29 // *** ViennaCL
30 //
31 #include "viennacl/scalar.hpp"
34 #include "viennacl/ell_matrix.hpp"
35 #include "viennacl/hyb_matrix.hpp"
36 #include "viennacl/vector.hpp"
38 #include "viennacl/linalg/prod.hpp"
40 #include "viennacl/linalg/ilu.hpp"
44 
47 
48 
49 //
50 // -------------------------------------------------------------
51 //
52 template<typename ScalarType>
54 {
55  if (s1 != s2)
56  return (s1 - s2) / std::max(fabs(s1), std::fabs(s2));
57  return 0;
58 }
59 
60 template<typename ScalarType>
61 ScalarType diff(std::vector<ScalarType> & v1, viennacl::vector<ScalarType> & v2)
62 {
63  std::vector<ScalarType> v2_cpu(v2.size());
65  viennacl::copy(v2.begin(), v2.end(), v2_cpu.begin());
66 
67  for (unsigned int i=0;i<v1.size(); ++i)
68  {
69  if ( std::max( std::fabs(v2_cpu[i]), std::fabs(v1[i]) ) > 0 )
70  {
71  //if (std::max( std::fabs(v2_cpu[i]), std::fabs(v1[i]) ) < 1e-10 ) //absolute tolerance (avoid round-off issues)
72  // v2_cpu[i] = 0;
73  //else
74  v2_cpu[i] = std::fabs(v2_cpu[i] - v1[i]) / std::max( std::fabs(v2_cpu[i]), std::fabs(v1[i]) );
75  }
76  else
77  v2_cpu[i] = 0.0;
78 
79  if (v2_cpu[i] > 0.0001)
80  {
81  //std::cout << "Neighbor: " << i-1 << ": " << v1[i-1] << " vs. " << v2_cpu[i-1] << std::endl;
82  std::cout << "Error at entry " << i << ": Should: " << v1[i] << " vs. Is: " << v2[i] << std::endl;
83  //std::cout << "Neighbor: " << i+1 << ": " << v1[i+1] << " vs. " << v2_cpu[i+1] << std::endl;
84  exit(EXIT_FAILURE);
85  }
86  }
87 
88  ScalarType norm_inf = 0;
89  for (std::size_t i=0; i<v2_cpu.size(); ++i)
90  norm_inf = std::max<ScalarType>(norm_inf, std::fabs(v2_cpu[i]));
91 
92  return norm_inf;
93 }
94 
95 
96 template<typename IndexT, typename NumericT, typename SparseMatrixT>
97 NumericT diff(std::vector<std::map<IndexT, NumericT> > & cpu_A, SparseMatrixT & vcl_A)
98 {
99  typedef typename std::map<IndexT, NumericT>::const_iterator RowIterator;
100 
101  std::vector<std::map<IndexT, NumericT> > from_gpu(vcl_A.size1());
102 
104  viennacl::copy(vcl_A, from_gpu);
105 
106  NumericT error = 0;
107 
108  //step 1: compare all entries from cpu_A with vcl_A:
109  for (std::size_t i=0; i<cpu_A.size(); ++i)
110  {
111  //std::cout << "Row " << row_it.index1() << ": " << std::endl;
112  for (RowIterator it = cpu_A[i].begin(); it != cpu_A[i].end(); ++it)
113  {
114  //std::cout << "(" << col_it.index2() << ", " << *col_it << std::endl;
115  NumericT current_error = 0;
116  NumericT val_cpu_A = it->second;
117  NumericT val_gpu_A = from_gpu[i][it->first];
118 
119  NumericT max_val = std::max(std::fabs(val_cpu_A), std::fabs(val_gpu_A));
120  if (max_val > 0)
121  current_error = std::fabs(val_cpu_A - val_gpu_A) / max_val;
122  if (current_error > error)
123  error = current_error;
124  }
125  }
126 
127  //step 2: compare all entries from gpu_matrix with cpu_matrix (sparsity pattern might differ):
128  //std::cout << "ViennaCL matrix: " << std::endl;
129  for (std::size_t i=0; i<from_gpu.size(); ++i)
130  {
131  //std::cout << "Row " << row_it.index1() << ": " << std::endl;
132  for (RowIterator it = from_gpu[i].begin(); it != from_gpu[i].end(); ++it)
133  {
134  //std::cout << "(" << col_it.index2() << ", " << *col_it << std::endl;
135  NumericT current_error = 0;
136  NumericT val_gpu_A = it->second;
137  NumericT val_cpu_A = cpu_A[i][it->first];
138 
139  NumericT max_val = std::max(std::fabs(val_cpu_A), std::fabs(val_gpu_A));
140  if (max_val > 0)
141  current_error = std::fabs(val_cpu_A - val_gpu_A) / max_val;
142  if (current_error > error)
143  error = current_error;
144  }
145  }
146 
147  return error;
148 }
149 
150 // computes x = alpha * A * y + beta * x
151 template<typename IndexT, typename NumericT, typename VectorT>
152 void sparse_prod(std::vector<std::map<IndexT, NumericT> > const & A, VectorT const & y, VectorT & x, NumericT alpha, NumericT beta)
153 {
154  typedef typename std::map<IndexT, NumericT>::const_iterator RowIterator;
155 
156  for (std::size_t i=0; i<A.size(); ++i)
157  {
158  NumericT val = 0;
159  for (RowIterator it = A[i].begin(); it != A[i].end(); ++it)
160  val += it->second * y[it->first];
161  x[i] = alpha * val + beta * x[i];
162  }
163 }
164 
165 //
166 // -------------------------------------------------------------
167 //
168 template< typename NumericT, typename Epsilon >
169 int test(Epsilon const& epsilon)
170 {
171  int retval = EXIT_SUCCESS;
172 
174 
175  // --------------------------------------------------------------------------
176  NumericT alpha = static_cast<NumericT>(2.786);
177  NumericT beta = static_cast<NumericT>(1.432);
178 
179  std::vector<NumericT> rhs;
180  std::vector<NumericT> result;
181  std::vector<std::map<unsigned int, NumericT> > std_matrix;
182 
183  if (viennacl::io::read_matrix_market_file(std_matrix, "../examples/testdata/mat65k.mtx") == EXIT_FAILURE)
184  {
185  std::cout << "Error reading Matrix file" << std::endl;
186  return EXIT_FAILURE;
187  }
188  //unsigned int cg_mat_size = cg_mat.size();
189  std::cout << "done reading matrix" << std::endl;
190 
191 
192  rhs.resize(std_matrix.size());
193  for (std::size_t i=0; i<rhs.size(); ++i)
194  {
195  std_matrix[i][static_cast<unsigned int>(i)] = NumericT(0.5); // Get rid of round-off errors by making row-sums unequal to zero:
196  rhs[i] = NumericT(1) + randomNumber();
197  }
198 
199  result = rhs;
200 
201 
202  viennacl::vector<NumericT> vcl_rhs(rhs.size());
203  viennacl::vector<NumericT> vcl_result(result.size());
204  viennacl::vector<NumericT> vcl_result2(result.size());
205  viennacl::compressed_matrix<NumericT> vcl_compressed_matrix(rhs.size(), rhs.size());
206  viennacl::coordinate_matrix<NumericT> vcl_coordinate_matrix(rhs.size(), rhs.size());
207  viennacl::ell_matrix<NumericT> vcl_ell_matrix;
208  viennacl::hyb_matrix<NumericT> vcl_hyb_matrix;
209 
210  viennacl::copy(rhs.begin(), rhs.end(), vcl_rhs.begin());
211  viennacl::copy(std_matrix, vcl_compressed_matrix);
212  viennacl::copy(std_matrix, vcl_coordinate_matrix);
213 
214  // --------------------------------------------------------------------------
215  std::cout << "Testing products: compressed_matrix" << std::endl;
216  sparse_prod(std_matrix, rhs, result, NumericT(1), NumericT(0));
217  {
218  viennacl::scheduler::statement my_statement(vcl_result, viennacl::op_assign(), viennacl::linalg::prod(vcl_compressed_matrix, vcl_rhs));
219  viennacl::scheduler::execute(my_statement);
220  }
221  vcl_result = viennacl::linalg::prod(vcl_compressed_matrix, vcl_rhs);
222 
223  if ( std::fabs(diff(result, vcl_result)) > epsilon )
224  {
225  std::cout << "# Error at operation: matrix-vector product with compressed_matrix" << std::endl;
226  std::cout << " diff: " << std::fabs(diff(result, vcl_result)) << std::endl;
227  retval = EXIT_FAILURE;
228  }
229 
230  std::cout << "Testing products: coordinate_matrix" << std::endl;
231  for (std::size_t i=0; i<rhs.size(); ++i)
232  rhs[i] *= NumericT(1.1);
233  vcl_rhs *= NumericT(1.1);
234  sparse_prod(std_matrix, rhs, result, NumericT(1), NumericT(0));
235  {
236  viennacl::scheduler::statement my_statement(vcl_result, viennacl::op_assign(), viennacl::linalg::prod(vcl_coordinate_matrix, vcl_rhs));
237  viennacl::scheduler::execute(my_statement);
238  }
239 
240  if ( std::fabs(diff(result, vcl_result)) > epsilon )
241  {
242  std::cout << "# Error at operation: matrix-vector product with coordinate_matrix" << std::endl;
243  std::cout << " diff: " << std::fabs(diff(result, vcl_result)) << std::endl;
244  retval = EXIT_FAILURE;
245  }
246 
247  //std::cout << "Copying ell_matrix" << std::endl;
248  viennacl::copy(std_matrix, vcl_ell_matrix);
249  std_matrix.clear();
250  viennacl::copy(vcl_ell_matrix, std_matrix);// just to check that it's works
251 
252 
253  std::cout << "Testing products: ell_matrix" << std::endl;
254  for (std::size_t i=0; i<rhs.size(); ++i)
255  rhs[i] *= NumericT(1.1);
256  vcl_rhs *= NumericT(1.1);
257  sparse_prod(std_matrix, rhs, result, NumericT(1), NumericT(0));
258  {
259  //viennacl::scheduler::statement my_statement(vcl_result, viennacl::op_assign(), viennacl::linalg::prod(vcl_ell_matrix, vcl_rhs));
260  //viennacl::scheduler::execute(my_statement);
261  }
262  vcl_result = viennacl::linalg::prod(vcl_ell_matrix, vcl_rhs);
263 
264  if ( std::fabs(diff(result, vcl_result)) > epsilon )
265  {
266  std::cout << "# Error at operation: matrix-vector product with ell_matrix" << std::endl;
267  std::cout << " diff: " << std::fabs(diff(result, vcl_result)) << std::endl;
268  retval = EXIT_FAILURE;
269  }
270 
271  //std::cout << "Copying hyb_matrix" << std::endl;
272  viennacl::copy(std_matrix, vcl_hyb_matrix);
273  std_matrix.clear();
274  viennacl::copy(vcl_hyb_matrix, std_matrix);// just to check that it's works
275  viennacl::copy(std_matrix, vcl_hyb_matrix);
276 
277  std::cout << "Testing products: hyb_matrix" << std::endl;
278  for (std::size_t i=0; i<rhs.size(); ++i)
279  rhs[i] *= NumericT(1.1);
280  vcl_rhs *= NumericT(1.1);
281  sparse_prod(std_matrix, rhs, result, NumericT(1), NumericT(0));
282  {
283  viennacl::scheduler::statement my_statement(vcl_result, viennacl::op_assign(), viennacl::linalg::prod(vcl_hyb_matrix, vcl_rhs));
284  viennacl::scheduler::execute(my_statement);
285  }
286 
287  if ( std::fabs(diff(result, vcl_result)) > epsilon )
288  {
289  std::cout << "# Error at operation: matrix-vector product with hyb_matrix" << std::endl;
290  std::cout << " diff: " << std::fabs(diff(result, vcl_result)) << std::endl;
291  retval = EXIT_FAILURE;
292  }
293 
294 
295  // --------------------------------------------------------------------------
296  // --------------------------------------------------------------------------
297  copy(rhs.begin(), rhs.end(), vcl_rhs.begin());
298  copy(result.begin(), result.end(), vcl_result.begin());
299  copy(result.begin(), result.end(), vcl_result2.begin());
300  copy(std_matrix, vcl_compressed_matrix);
301  copy(std_matrix, vcl_coordinate_matrix);
302  copy(std_matrix, vcl_ell_matrix);
303  copy(std_matrix, vcl_hyb_matrix);
304 
305  std::cout << "Testing scaled additions of products and vectors: compressed_matrix" << std::endl;
306  for (std::size_t i=0; i<rhs.size(); ++i)
307  rhs[i] *= NumericT(1.1);
308  vcl_rhs *= NumericT(1.1);
309  sparse_prod(std_matrix, rhs, result, NumericT(alpha), beta);
310  {
311  viennacl::scheduler::statement my_statement(vcl_result2, viennacl::op_assign(), alpha * viennacl::linalg::prod(vcl_compressed_matrix, vcl_rhs) + beta * vcl_result);
312  viennacl::scheduler::execute(my_statement);
313  }
314 
315  if ( std::fabs(diff(result, vcl_result2)) > epsilon )
316  {
317  std::cout << "# Error at operation: matrix-vector product (compressed_matrix) with scaled additions" << std::endl;
318  std::cout << " diff: " << std::fabs(diff(result, vcl_result2)) << std::endl;
319  retval = EXIT_FAILURE;
320  }
321 
322 
323  std::cout << "Testing scaled additions of products and vectors: coordinate_matrix" << std::endl;
324  copy(result.begin(), result.end(), vcl_result.begin());
325  for (std::size_t i=0; i<rhs.size(); ++i)
326  rhs[i] *= NumericT(1.1);
327  vcl_rhs *= NumericT(1.1);
328  sparse_prod(std_matrix, rhs, result, NumericT(alpha), beta);
329  {
330  viennacl::scheduler::statement my_statement(vcl_result2, viennacl::op_assign(), alpha * viennacl::linalg::prod(vcl_coordinate_matrix, vcl_rhs) + beta * vcl_result);
331  viennacl::scheduler::execute(my_statement);
332  }
333 
334  if ( std::fabs(diff(result, vcl_result2)) > epsilon )
335  {
336  std::cout << "# Error at operation: matrix-vector product (coordinate_matrix) with scaled additions" << std::endl;
337  std::cout << " diff: " << std::fabs(diff(result, vcl_result2)) << std::endl;
338  retval = EXIT_FAILURE;
339  }
340 
341  std::cout << "Testing scaled additions of products and vectors: ell_matrix" << std::endl;
342  copy(result.begin(), result.end(), vcl_result.begin());
343  for (std::size_t i=0; i<rhs.size(); ++i)
344  rhs[i] *= NumericT(1.1);
345  vcl_rhs *= NumericT(1.1);
346  sparse_prod(std_matrix, rhs, result, NumericT(alpha), beta);
347  {
348  viennacl::scheduler::statement my_statement(vcl_result2, viennacl::op_assign(), alpha * viennacl::linalg::prod(vcl_ell_matrix, vcl_rhs) + beta * vcl_result);
349  viennacl::scheduler::execute(my_statement);
350  }
351 
352  if ( std::fabs(diff(result, vcl_result2)) > epsilon )
353  {
354  std::cout << "# Error at operation: matrix-vector product (ell_matrix) with scaled additions" << std::endl;
355  std::cout << " diff: " << std::fabs(diff(result, vcl_result2)) << std::endl;
356  retval = EXIT_FAILURE;
357  }
358 
359  std::cout << "Testing scaled additions of products and vectors: hyb_matrix" << std::endl;
360  copy(result.begin(), result.end(), vcl_result.begin());
361  for (std::size_t i=0; i<rhs.size(); ++i)
362  rhs[i] *= NumericT(1.1);
363  vcl_rhs *= NumericT(1.1);
364  sparse_prod(std_matrix, rhs, result, NumericT(alpha), beta);
365  {
366  viennacl::scheduler::statement my_statement(vcl_result2, viennacl::op_assign(), alpha * viennacl::linalg::prod(vcl_hyb_matrix, vcl_rhs) + beta * vcl_result);
367  viennacl::scheduler::execute(my_statement);
368  }
369 
370  if ( std::fabs(diff(result, vcl_result2)) > epsilon )
371  {
372  std::cout << "# Error at operation: matrix-vector product (hyb_matrix) with scaled additions" << std::endl;
373  std::cout << " diff: " << std::fabs(diff(result, vcl_result2)) << std::endl;
374  retval = EXIT_FAILURE;
375  }
376 
377 
378  // --------------------------------------------------------------------------
379  return retval;
380 }
381 //
382 // -------------------------------------------------------------
383 //
384 int main()
385 {
386  std::cout << std::endl;
387  std::cout << "----------------------------------------------" << std::endl;
388  std::cout << "----------------------------------------------" << std::endl;
389  std::cout << "## Test :: Sparse Matrices" << std::endl;
390  std::cout << "----------------------------------------------" << std::endl;
391  std::cout << "----------------------------------------------" << std::endl;
392  std::cout << std::endl;
393 
394  int retval = EXIT_SUCCESS;
395 
396  std::cout << std::endl;
397  std::cout << "----------------------------------------------" << std::endl;
398  std::cout << std::endl;
399  {
400  typedef float NumericT;
401  NumericT epsilon = static_cast<NumericT>(1E-4);
402  std::cout << "# Testing setup:" << std::endl;
403  std::cout << " eps: " << epsilon << std::endl;
404  std::cout << " numeric: float" << std::endl;
405  retval = test<NumericT>(epsilon);
406  if ( retval == EXIT_SUCCESS )
407  std::cout << "# Test passed" << std::endl;
408  else
409  return retval;
410  }
411  std::cout << std::endl;
412  std::cout << "----------------------------------------------" << std::endl;
413  std::cout << std::endl;
414 
415 #ifdef VIENNACL_WITH_OPENCL
417 #endif
418  {
419  {
420  typedef double NumericT;
421  NumericT epsilon = 1.0E-13;
422  std::cout << "# Testing setup:" << std::endl;
423  std::cout << " eps: " << epsilon << std::endl;
424  std::cout << " numeric: double" << std::endl;
425  retval = test<NumericT>(epsilon);
426  if ( retval == EXIT_SUCCESS )
427  std::cout << "# Test passed" << std::endl;
428  else
429  return retval;
430  }
431  std::cout << std::endl;
432  std::cout << "----------------------------------------------" << std::endl;
433  std::cout << std::endl;
434  }
435 #ifdef VIENNACL_WITH_OPENCL
436  else
437  std::cout << "No double precision support, skipping test..." << std::endl;
438 #endif
439 
440 
441  std::cout << std::endl;
442  std::cout << "------- Test completed --------" << std::endl;
443  std::cout << std::endl;
444 
445  return retval;
446 }
Sparse matrix class using a hybrid format composed of the ELL and CSR format for storing the nonzeros...
Definition: forwards.h:406
A reader and writer for the matrix market format is implemented here.
This class represents a single scalar value on the GPU and behaves mostly like a built-in scalar type...
Definition: forwards.h:227
Generic interface for the l^2-norm. See viennacl/linalg/vector_operations.hpp for implementations...
int test(Epsilon const &epsilon)
Generic interface for matrix-vector and matrix-matrix products. See viennacl/linalg/vector_operations...
Some helper routines for reading/writing/printing scheduler expressions.
A tag class representing assignment.
Definition: forwards.h:81
void finish()
Synchronizes the execution. finish() will only return after all compute kernels (CUDA, OpenCL) have completed.
Definition: memory.hpp:54
void execute(statement const &s)
Definition: execute.hpp:279
viennacl::scalar< int > s2
viennacl::scalar< float > s1
T max(const T &lhs, const T &rhs)
Maximum.
Definition: util.hpp:59
viennacl::ocl::device const & current_device()
Convenience function for returning the active device in the current context.
Definition: backend.hpp:351
Implementation of the coordinate_matrix class.
float NumericT
Definition: bisect.cpp:40
viennacl::vector< float > v1
Implementation of the hyb_matrix class.
VectorT prod(std::vector< std::vector< T, A1 >, A2 > const &matrix, VectorT const &vector)
Definition: prod.hpp:102
Random number generator for returning uniformly distributed values in the closed interval [0...
Definition: random.hpp:44
Sparse matrix class using the ELLPACK format for storing the nonzeros.
Definition: ell_matrix.hpp:53
void sparse_prod(std::vector< std::map< IndexT, NumericT > > const &A, VectorT const &y, VectorT &x, NumericT alpha, NumericT beta)
iterator begin()
Returns an iterator pointing to the beginning of the vector (STL like)
Definition: vector.hpp:841
Implementations of incomplete factorization preconditioners. Convenience header file.
Implementation of the compressed_matrix class.
bool double_support() const
ViennaCL convenience function: Returns true if the device supports double precision.
Definition: device.hpp:956
Implementation of the ell_matrix class.
Proxy classes for vectors.
viennacl::vector< int > v2
The vector type with operator-overloads and proxy classes is defined here. Linear algebra operations ...
int main()
T norm_inf(std::vector< T, A > const &v1)
Definition: norm_inf.hpp:60
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) ...
A small collection of sequential random number generators.
size_type size() const
Returns the length of the vector (cf. std::vector)
Definition: vector_def.hpp:118
float ScalarType
Definition: fft_1d.cpp:42
Provides the datastructures for dealing with a single statement such as 'x = y + z;'.
The main class for representing a statement such as x = inner_prod(y,z); at runtime.
Definition: forwards.h:502
ScalarType diff(ScalarType &s1, viennacl::scalar< ScalarType > &s2)
long read_matrix_market_file(MatrixT &mat, const char *file, long index_base=1)
Reads a sparse matrix from a file (MatrixMarket format)
iterator end()
Returns an iterator pointing to the end of the vector (STL like)
Definition: vector.hpp:848
Common routines used within ILU-type preconditioners.
Implementation of the ViennaCL scalar class.
A sparse square matrix, where entries are stored as triplets (i,j, val), where i and j are the row an...