ViennaCL - The Vienna Computing Library  1.6.0
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-2014, 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 #ifndef NDEBUG
24  #define NDEBUG
25 #endif
26 
27 //
28 // *** System
29 //
30 #include <iostream>
31 
32 //
33 // *** Boost
34 //
35 #include <boost/numeric/ublas/io.hpp>
36 #include <boost/numeric/ublas/triangular.hpp>
37 #include <boost/numeric/ublas/matrix_sparse.hpp>
38 #include <boost/numeric/ublas/matrix.hpp>
39 #include <boost/numeric/ublas/matrix_proxy.hpp>
40 #include <boost/numeric/ublas/lu.hpp>
41 #include <boost/numeric/ublas/io.hpp>
42 #include <boost/numeric/ublas/operation_sparse.hpp>
43 
44 //
45 // *** ViennaCL
46 //
47 //#define VIENNACL_DEBUG_ALL
48 #define VIENNACL_WITH_UBLAS 1
49 #include "viennacl/scalar.hpp"
52 #include "viennacl/ell_matrix.hpp"
53 #include "viennacl/hyb_matrix.hpp"
54 #include "viennacl/vector.hpp"
56 #include "viennacl/linalg/prod.hpp"
58 #include "viennacl/linalg/ilu.hpp"
63 
66 
67 //
68 // -------------------------------------------------------------
69 //
70 using namespace boost::numeric;
71 //
72 // -------------------------------------------------------------
73 //
74 template<typename ScalarType>
76 {
77  if (s1 != s2)
78  return (s1 - s2) / std::max(fabs(s1), std::fabs(s2));
79  return 0;
80 }
81 
82 template<typename ScalarType>
83 ScalarType diff(ublas::vector<ScalarType> & v1, viennacl::vector<ScalarType> & v2)
84 {
85  ublas::vector<ScalarType> v2_cpu(v2.size());
87  viennacl::copy(v2.begin(), v2.end(), v2_cpu.begin());
88 
89  for (unsigned int i=0;i<v1.size(); ++i)
90  {
91  if ( std::max( std::fabs(v2_cpu[i]), std::fabs(v1[i]) ) > 0 )
92  {
93  //if (std::max( std::fabs(v2_cpu[i]), std::fabs(v1[i]) ) < 1e-10 ) //absolute tolerance (avoid round-off issues)
94  // v2_cpu[i] = 0;
95  //else
96  v2_cpu[i] = std::fabs(v2_cpu[i] - v1[i]) / std::max( std::fabs(v2_cpu[i]), std::fabs(v1[i]) );
97  }
98  else
99  v2_cpu[i] = 0.0;
100 
101  if (v2_cpu[i] > 0.0001)
102  {
103  //std::cout << "Neighbor: " << i-1 << ": " << v1[i-1] << " vs. " << v2_cpu[i-1] << std::endl;
104  std::cout << "Error at entry " << i << ": " << v1[i] << " vs. " << v2_cpu[i] << std::endl;
105  //std::cout << "Neighbor: " << i+1 << ": " << v1[i+1] << " vs. " << v2_cpu[i+1] << std::endl;
106  exit(EXIT_FAILURE);
107  }
108  }
109 
110  return norm_inf(v2_cpu);
111 }
112 
113 
114 template<typename ScalarType, typename VCL_MATRIX>
115 ScalarType diff(ublas::compressed_matrix<ScalarType> & cpu_matrix, VCL_MATRIX & gpu_matrix)
116 {
117  typedef ublas::compressed_matrix<ScalarType> CPU_MATRIX;
118  CPU_MATRIX from_gpu;
119 
121  viennacl::copy(gpu_matrix, from_gpu);
122 
123  ScalarType error = 0;
124 
125  //step 1: compare all entries from cpu_matrix with gpu_matrix:
126  //std::cout << "Ublas matrix: " << std::endl;
127  for (typename CPU_MATRIX::const_iterator1 row_it = cpu_matrix.begin1();
128  row_it != cpu_matrix.end1();
129  ++row_it)
130  {
131  //std::cout << "Row " << row_it.index1() << ": " << std::endl;
132  for (typename CPU_MATRIX::const_iterator2 col_it = row_it.begin();
133  col_it != row_it.end();
134  ++col_it)
135  {
136  //std::cout << "(" << col_it.index2() << ", " << *col_it << std::endl;
137  ScalarType current_error = 0;
138 
139  if ( std::max( std::fabs(cpu_matrix(col_it.index1(), col_it.index2())),
140  std::fabs(from_gpu(col_it.index1(), col_it.index2())) ) > 0 )
141  current_error = std::fabs(cpu_matrix(col_it.index1(), col_it.index2()) - from_gpu(col_it.index1(), col_it.index2()))
142  / std::max( std::fabs(cpu_matrix(col_it.index1(), col_it.index2())),
143  std::fabs(from_gpu(col_it.index1(), col_it.index2())) );
144  if (current_error > error)
145  error = current_error;
146  }
147  }
148 
149  //step 2: compare all entries from gpu_matrix with cpu_matrix (sparsity pattern might differ):
150  //std::cout << "ViennaCL matrix: " << std::endl;
151  for (typename CPU_MATRIX::const_iterator1 row_it = from_gpu.begin1();
152  row_it != from_gpu.end1();
153  ++row_it)
154  {
155  //std::cout << "Row " << row_it.index1() << ": " << std::endl;
156  for (typename CPU_MATRIX::const_iterator2 col_it = row_it.begin();
157  col_it != row_it.end();
158  ++col_it)
159  {
160  //std::cout << "(" << col_it.index2() << ", " << *col_it << std::endl;
161  ScalarType current_error = 0;
162 
163  if ( std::max( std::fabs(cpu_matrix(col_it.index1(), col_it.index2())),
164  std::fabs(from_gpu(col_it.index1(), col_it.index2())) ) > 0 )
165  current_error = std::fabs(cpu_matrix(col_it.index1(), col_it.index2()) - from_gpu(col_it.index1(), col_it.index2()))
166  / std::max( std::fabs(cpu_matrix(col_it.index1(), col_it.index2())),
167  std::fabs(from_gpu(col_it.index1(), col_it.index2())) );
168  if (current_error > error)
169  error = current_error;
170  }
171  }
172 
173  return error;
174 }
175 
176 //
177 // -------------------------------------------------------------
178 //
179 template< typename NumericT, typename Epsilon >
180 int test(Epsilon const& epsilon)
181 {
182  int retval = EXIT_SUCCESS;
183 
184  // --------------------------------------------------------------------------
185  NumericT alpha = static_cast<NumericT>(2.786);
186  NumericT beta = static_cast<NumericT>(1.432);
187 
188  ublas::vector<NumericT> rhs;
189  ublas::vector<NumericT> result;
190  ublas::compressed_matrix<NumericT> ublas_matrix;
191 
192  if (viennacl::io::read_matrix_market_file(ublas_matrix, "../examples/testdata/mat65k.mtx") == EXIT_FAILURE)
193  {
194  std::cout << "Error reading Matrix file" << std::endl;
195  return EXIT_FAILURE;
196  }
197  //unsigned int cg_mat_size = cg_mat.size();
198  std::cout << "done reading matrix" << std::endl;
199 
200 
201  rhs.resize(ublas_matrix.size2());
202  for (std::size_t i=0; i<rhs.size(); ++i)
203  {
204  ublas_matrix(i,i) = NumericT(0.5); // Get rid of round-off errors by making row-sums unequal to zero:
205  rhs[i] = NumericT(1) + random<NumericT>();
206  }
207 
208  result = rhs;
209 
210 
211  viennacl::vector<NumericT> vcl_rhs(rhs.size());
212  viennacl::vector<NumericT> vcl_result(result.size());
213  viennacl::vector<NumericT> vcl_result2(result.size());
214  viennacl::compressed_matrix<NumericT> vcl_compressed_matrix(rhs.size(), rhs.size());
215  viennacl::coordinate_matrix<NumericT> vcl_coordinate_matrix(rhs.size(), rhs.size());
216  viennacl::ell_matrix<NumericT> vcl_ell_matrix;
217  viennacl::hyb_matrix<NumericT> vcl_hyb_matrix;
218 
219  viennacl::copy(rhs.begin(), rhs.end(), vcl_rhs.begin());
220  viennacl::copy(ublas_matrix, vcl_compressed_matrix);
221  viennacl::copy(ublas_matrix, vcl_coordinate_matrix);
222 
223  // --------------------------------------------------------------------------
224  std::cout << "Testing products: compressed_matrix" << std::endl;
225  result = viennacl::linalg::prod(ublas_matrix, rhs);
226  {
227  viennacl::scheduler::statement my_statement(vcl_result, viennacl::op_assign(), viennacl::linalg::prod(vcl_compressed_matrix, vcl_rhs));
228  viennacl::scheduler::execute(my_statement);
229  }
230  vcl_result = viennacl::linalg::prod(vcl_compressed_matrix, vcl_rhs);
231 
232  if ( std::fabs(diff(result, vcl_result)) > epsilon )
233  {
234  std::cout << "# Error at operation: matrix-vector product with compressed_matrix" << std::endl;
235  std::cout << " diff: " << std::fabs(diff(result, vcl_result)) << std::endl;
236  retval = EXIT_FAILURE;
237  }
238 
239  std::cout << "Testing products: coordinate_matrix" << std::endl;
240  rhs *= NumericT(1.1);
241  vcl_rhs *= NumericT(1.1);
242  result = viennacl::linalg::prod(ublas_matrix, rhs);
243  {
244  viennacl::scheduler::statement my_statement(vcl_result, viennacl::op_assign(), viennacl::linalg::prod(vcl_coordinate_matrix, vcl_rhs));
245  viennacl::scheduler::execute(my_statement);
246  }
247 
248  if ( std::fabs(diff(result, vcl_result)) > epsilon )
249  {
250  std::cout << "# Error at operation: matrix-vector product with coordinate_matrix" << std::endl;
251  std::cout << " diff: " << std::fabs(diff(result, vcl_result)) << std::endl;
252  retval = EXIT_FAILURE;
253  }
254 
255  result = alpha * viennacl::linalg::prod(ublas_matrix, rhs) + beta * result;
256  {
257  viennacl::scheduler::statement my_statement(vcl_result2, viennacl::op_assign(), alpha * viennacl::linalg::prod(vcl_coordinate_matrix, vcl_rhs) + beta * vcl_result);
258  viennacl::scheduler::execute(my_statement);
259  }
260 
261  if ( std::fabs(diff(result, vcl_result2)) > epsilon )
262  {
263  std::cout << "# Error at operation: matrix-vector product (coordinate_matrix) with scaled additions" << std::endl;
264  std::cout << " diff: " << std::fabs(diff(result, vcl_result2)) << std::endl;
265  retval = EXIT_FAILURE;
266  }
267 
268  //std::cout << "Copying ell_matrix" << std::endl;
269  viennacl::copy(ublas_matrix, vcl_ell_matrix);
270  ublas_matrix.clear();
271  viennacl::copy(vcl_ell_matrix, ublas_matrix);// just to check that it's works
272 
273 
274  std::cout << "Testing products: ell_matrix" << std::endl;
275  rhs *= NumericT(1.1);
276  vcl_rhs *= NumericT(1.1);
277  result = viennacl::linalg::prod(ublas_matrix, rhs);
278  {
279  //viennacl::scheduler::statement my_statement(vcl_result, viennacl::op_assign(), viennacl::linalg::prod(vcl_ell_matrix, vcl_rhs));
280  //viennacl::scheduler::execute(my_statement);
281  }
282  vcl_result = viennacl::linalg::prod(vcl_ell_matrix, vcl_rhs);
283 
284  if ( std::fabs(diff(result, vcl_result)) > epsilon )
285  {
286  std::cout << "# Error at operation: matrix-vector product with ell_matrix" << std::endl;
287  std::cout << " diff: " << std::fabs(diff(result, vcl_result)) << std::endl;
288  retval = EXIT_FAILURE;
289  }
290 
291  //std::cout << "Copying hyb_matrix" << std::endl;
292  viennacl::copy(ublas_matrix, vcl_hyb_matrix);
293  ublas_matrix.clear();
294  viennacl::copy(vcl_hyb_matrix, ublas_matrix);// just to check that it's works
295  viennacl::copy(ublas_matrix, vcl_hyb_matrix);
296 
297  std::cout << "Testing products: hyb_matrix" << std::endl;
298  rhs *= NumericT(1.1);
299  vcl_rhs *= NumericT(1.1);
300  result = viennacl::linalg::prod(ublas_matrix, rhs);
301  {
302  viennacl::scheduler::statement my_statement(vcl_result, viennacl::op_assign(), viennacl::linalg::prod(vcl_hyb_matrix, vcl_rhs));
303  viennacl::scheduler::execute(my_statement);
304  }
305 
306  if ( std::fabs(diff(result, vcl_result)) > epsilon )
307  {
308  std::cout << "# Error at operation: matrix-vector product with hyb_matrix" << std::endl;
309  std::cout << " diff: " << std::fabs(diff(result, vcl_result)) << std::endl;
310  retval = EXIT_FAILURE;
311  }
312 
313 
314  // --------------------------------------------------------------------------
315  // --------------------------------------------------------------------------
316  copy(rhs.begin(), rhs.end(), vcl_rhs.begin());
317  copy(result.begin(), result.end(), vcl_result.begin());
318  copy(result.begin(), result.end(), vcl_result2.begin());
319  copy(ublas_matrix, vcl_compressed_matrix);
320  copy(ublas_matrix, vcl_coordinate_matrix);
321  copy(ublas_matrix, vcl_ell_matrix);
322  copy(ublas_matrix, vcl_hyb_matrix);
323 
324  std::cout << "Testing scaled additions of products and vectors: compressed_matrix" << std::endl;
325  rhs *= NumericT(1.1);
326  vcl_rhs *= NumericT(1.1);
327  result = alpha * viennacl::linalg::prod(ublas_matrix, rhs) + beta * result;
328  {
329  viennacl::scheduler::statement my_statement(vcl_result2, viennacl::op_assign(), alpha * viennacl::linalg::prod(vcl_compressed_matrix, vcl_rhs) + beta * vcl_result);
330  viennacl::scheduler::execute(my_statement);
331  }
332 
333  if ( std::fabs(diff(result, vcl_result2)) > epsilon )
334  {
335  std::cout << "# Error at operation: matrix-vector product (compressed_matrix) with scaled additions" << std::endl;
336  std::cout << " diff: " << std::fabs(diff(result, vcl_result2)) << std::endl;
337  retval = EXIT_FAILURE;
338  }
339 
340 
341  std::cout << "Testing scaled additions of products and vectors: coordinate_matrix" << std::endl;
342  copy(result.begin(), result.end(), vcl_result.begin());
343  rhs *= NumericT(1.1);
344  vcl_rhs *= NumericT(1.1);
345  result = alpha * viennacl::linalg::prod(ublas_matrix, rhs) + beta * result;
346  {
347  viennacl::scheduler::statement my_statement(vcl_result2, viennacl::op_assign(), alpha * viennacl::linalg::prod(vcl_coordinate_matrix, vcl_rhs) + beta * vcl_result);
348  viennacl::scheduler::execute(my_statement);
349  }
350 
351  if ( std::fabs(diff(result, vcl_result2)) > epsilon )
352  {
353  std::cout << "# Error at operation: matrix-vector product (coordinate_matrix) with scaled additions" << std::endl;
354  std::cout << " diff: " << std::fabs(diff(result, vcl_result2)) << std::endl;
355  retval = EXIT_FAILURE;
356  }
357 
358  std::cout << "Testing scaled additions of products and vectors: ell_matrix" << std::endl;
359  copy(result.begin(), result.end(), vcl_result.begin());
360  rhs *= NumericT(1.1);
361  vcl_rhs *= NumericT(1.1);
362  result = alpha * viennacl::linalg::prod(ublas_matrix, rhs) + beta * result;
363  {
364  viennacl::scheduler::statement my_statement(vcl_result2, viennacl::op_assign(), alpha * viennacl::linalg::prod(vcl_ell_matrix, vcl_rhs) + beta * vcl_result);
365  viennacl::scheduler::execute(my_statement);
366  }
367 
368  if ( std::fabs(diff(result, vcl_result2)) > epsilon )
369  {
370  std::cout << "# Error at operation: matrix-vector product (ell_matrix) with scaled additions" << std::endl;
371  std::cout << " diff: " << std::fabs(diff(result, vcl_result2)) << std::endl;
372  retval = EXIT_FAILURE;
373  }
374 
375  std::cout << "Testing scaled additions of products and vectors: hyb_matrix" << std::endl;
376  copy(result.begin(), result.end(), vcl_result.begin());
377  rhs *= NumericT(1.1);
378  vcl_rhs *= NumericT(1.1);
379  result = alpha * viennacl::linalg::prod(ublas_matrix, rhs) + beta * result;
380  {
381  viennacl::scheduler::statement my_statement(vcl_result2, viennacl::op_assign(), alpha * viennacl::linalg::prod(vcl_hyb_matrix, vcl_rhs) + beta * vcl_result);
382  viennacl::scheduler::execute(my_statement);
383  }
384 
385  if ( std::fabs(diff(result, vcl_result2)) > epsilon )
386  {
387  std::cout << "# Error at operation: matrix-vector product (hyb_matrix) with scaled additions" << std::endl;
388  std::cout << " diff: " << std::fabs(diff(result, vcl_result2)) << std::endl;
389  retval = EXIT_FAILURE;
390  }
391 
392 
393  // --------------------------------------------------------------------------
394  return retval;
395 }
396 //
397 // -------------------------------------------------------------
398 //
399 int main()
400 {
401  std::cout << std::endl;
402  std::cout << "----------------------------------------------" << std::endl;
403  std::cout << "----------------------------------------------" << std::endl;
404  std::cout << "## Test :: Sparse Matrices" << std::endl;
405  std::cout << "----------------------------------------------" << std::endl;
406  std::cout << "----------------------------------------------" << std::endl;
407  std::cout << std::endl;
408 
409  int retval = EXIT_SUCCESS;
410 
411  std::cout << std::endl;
412  std::cout << "----------------------------------------------" << std::endl;
413  std::cout << std::endl;
414  {
415  typedef float NumericT;
416  NumericT epsilon = static_cast<NumericT>(1E-4);
417  std::cout << "# Testing setup:" << std::endl;
418  std::cout << " eps: " << epsilon << std::endl;
419  std::cout << " numeric: float" << std::endl;
420  retval = test<NumericT>(epsilon);
421  if ( retval == EXIT_SUCCESS )
422  std::cout << "# Test passed" << std::endl;
423  else
424  return retval;
425  }
426  std::cout << std::endl;
427  std::cout << "----------------------------------------------" << std::endl;
428  std::cout << std::endl;
429 
430 #ifdef VIENNACL_WITH_OPENCL
432 #endif
433  {
434  {
435  typedef double NumericT;
436  NumericT epsilon = 1.0E-13;
437  std::cout << "# Testing setup:" << std::endl;
438  std::cout << " eps: " << epsilon << std::endl;
439  std::cout << " numeric: double" << std::endl;
440  retval = test<NumericT>(epsilon);
441  if ( retval == EXIT_SUCCESS )
442  std::cout << "# Test passed" << std::endl;
443  else
444  return retval;
445  }
446  std::cout << std::endl;
447  std::cout << "----------------------------------------------" << std::endl;
448  std::cout << std::endl;
449  }
450 #ifdef VIENNACL_WITH_OPENCL
451  else
452  std::cout << "No double precision support, skipping test..." << std::endl;
453 #endif
454 
455 
456  std::cout << std::endl;
457  std::cout << "------- Test completed --------" << std::endl;
458  std::cout << std::endl;
459 
460  return retval;
461 }
Sparse matrix class using a hybrid format composed of the ELL and CSR format for storing the nonzeros...
Definition: forwards.h:405
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:226
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:80
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.
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:91
Sparse matrix class using the ELLPACK format for storing the nonzeros.
Definition: ell_matrix.hpp:53
iterator begin()
Returns an iterator pointing to the beginning of the vector (STL like)
Definition: vector.hpp:827
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) ...
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:504
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:834
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...