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
spmdm.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 // include necessary system headers
25 //
26 #include <iostream>
27 #include <cmath>
28 #include <vector>
29 #include <map>
30 
31 //
32 // ViennaCL includes
33 //
34 #include "viennacl/scalar.hpp"
35 #include "viennacl/vector.hpp"
36 #include "viennacl/matrix.hpp"
40 #include "viennacl/ell_matrix.hpp"
41 #include "viennacl/hyb_matrix.hpp"
42 #include "viennacl/linalg/prod.hpp" //generic matrix-vector product
43 #include "viennacl/linalg/norm_2.hpp" //generic l2-norm for vectors
46 
47 
48 template<typename NumericT>
49 int check_matrices(std::vector<std::vector<NumericT> > const & ref_mat,
50  std::vector<std::vector<NumericT> > const & mat,
51  NumericT eps)
52 {
53  if ( (ref_mat.size() != mat.size()) || (ref_mat[0].size() != mat[0].size()) )
54  return EXIT_FAILURE;
55 
56  for (std::size_t i = 0; i < ref_mat.size(); i++)
57  for (std::size_t j = 0; j < ref_mat[0].size(); j++)
58  {
59  NumericT rel_error = std::abs(ref_mat[i][j] - mat[i][j]) / std::max(std::abs(ref_mat[i][j]), std::abs(mat[i][j]));
60  if (rel_error > eps)
61  {
62  std::cout << "ERROR: Verification failed at (" << i <<", "<< j << "): "
63  << " Expected: " << ref_mat[i][j] << ", got: " << mat[i][j] << " (relative error: " << rel_error << ")" << std::endl;
64  return EXIT_FAILURE;
65  }
66  }
67 
68  std::cout << "Everything went well!" << std::endl;
69  return EXIT_SUCCESS;
70 }
71 
72 
73 // Computes C = A * B for a sparse matrix A and dense matrices B and C.
74 // C is initialized with zeros
75 template<typename IndexT, typename NumericT>
76 void compute_reference_result(std::vector<std::map<IndexT, NumericT> > const & A,
77  std::vector<std::vector<NumericT> > const & B,
78  std::vector<std::vector<NumericT> > & C)
79 {
80  typedef typename std::map<IndexT, NumericT>::const_iterator RowIterator;
81 
82  for (std::size_t i=0; i<C.size(); ++i)
83  for (RowIterator it = A[i].begin(); it != A[i].end(); ++it)
84  {
85  IndexT col_A = it->first;
86  NumericT val_A = it->second;
87 
88  for (std::size_t j=0; j<C[i].size(); ++j)
89  C[i][j] += val_A * B[col_A][j];
90  }
91 }
92 
93 
94 template<typename NumericT, typename ResultLayoutT, typename FactorLayoutT>
95 int test(NumericT epsilon)
96 {
97  int retVal = EXIT_SUCCESS;
98 
100 
101  std::vector<std::map<unsigned int, NumericT> > std_A;
102  if (viennacl::io::read_matrix_market_file(std_A, "../examples/testdata/mat65k.mtx") == EXIT_FAILURE)
103  {
104  std::cout << "Error reading Matrix file" << std::endl;
105  return EXIT_FAILURE;
106  }
107 
108  // add some extra weight to diagonal in order to avoid issues with round-off errors
109  for (std::size_t i=0; i<std_A.size(); ++i)
110  std_A[i][static_cast<unsigned int>(i)] *= NumericT(1.5);
111 
112  std::size_t cols_rhs = 5;
113 
118 
119  std::vector<std::vector<NumericT> > std_C(std_A.size(), std::vector<NumericT>(cols_rhs));
121 
122  viennacl::copy(std_A, compressed_A);
123  viennacl::copy(std_A, ell_A);
124  viennacl::copy(std_A, coo_A);
125  viennacl::copy(std_A, hyb_A);
126 
127  std::vector<std::vector<NumericT> > std_B(std_A.size(), std::vector<NumericT>(cols_rhs));
128  viennacl::matrix<NumericT, FactorLayoutT> B1(std_A.size(), cols_rhs);
130 
131  std::vector<std::vector<NumericT> > temp(std_A.size(), std::vector<NumericT>(cols_rhs));
132 
133  for (unsigned int i = 0; i < std_B.size(); i++)
134  for (unsigned int j = 0; j < std_B[i].size(); j++)
135  std_B[i][j] = NumericT(0.5) + NumericT(0.1) * randomNumber();
136  viennacl::copy(std_B, B1);
137 
138 
139  /* gold result */
140  compute_reference_result(std_A, std_B, std_C);
141 
142  /******************************************************************/
143  std::cout << "Testing compressed(CSR) lhs * dense rhs" << std::endl;
144  C = viennacl::linalg::prod(compressed_A, B1);
145 
146  for (std::size_t i=0; i<temp.size(); ++i)
147  for (std::size_t j=0; j<temp[i].size(); ++j)
148  temp[i][j] = 0;
149  viennacl::copy(C, temp);
150  retVal = check_matrices(std_C, temp, epsilon);
151  if (retVal != EXIT_SUCCESS)
152  {
153  std::cerr << "Test failed!" << std::endl;
154  return retVal;
155  }
156 
157  /******************************************************************/
158  std::cout << "Testing compressed(ELL) lhs * dense rhs" << std::endl;
159  C.clear();
160  C = viennacl::linalg::prod(ell_A, B1);
161 
162  for (std::size_t i=0; i<temp.size(); ++i)
163  for (std::size_t j=0; j<temp[i].size(); ++j)
164  temp[i][j] = 0;
165  viennacl::copy(C, temp);
166  retVal = check_matrices(std_C, temp, epsilon);
167  if (retVal != EXIT_SUCCESS)
168  {
169  std::cerr << "Test failed!" << std::endl;
170  return retVal;
171  }
172 
173  /******************************************************************/
174 
175  std::cout << "Testing compressed(COO) lhs * dense rhs" << std::endl;
176  C.clear();
177  C = viennacl::linalg::prod(coo_A, B1);
178 
179  for (std::size_t i=0; i<temp.size(); ++i)
180  for (std::size_t j=0; j<temp[i].size(); ++j)
181  temp[i][j] = 0;
182  viennacl::copy(C, temp);
183  retVal = check_matrices(std_C, temp, epsilon);
184  if (retVal != EXIT_SUCCESS)
185  {
186  std::cerr << "Test failed!" << std::endl;
187  return retVal;
188  }
189 
190  /******************************************************************/
191 
192  std::cout << "Testing compressed(HYB) lhs * dense rhs" << std::endl;
193  C.clear();
194  C = viennacl::linalg::prod(hyb_A, B1);
195 
196  for (std::size_t i=0; i<temp.size(); ++i)
197  for (std::size_t j=0; j<temp[i].size(); ++j)
198  temp[i][j] = 0;
199  viennacl::copy(C, temp);
200  retVal = check_matrices(std_C, temp, epsilon);
201  if (retVal != EXIT_SUCCESS)
202  {
203  std::cerr << "Test failed!" << std::endl;
204  return retVal;
205  }
206 
207  /******************************************************************/
208 
209 
211 
212  B2 = viennacl::trans(B1);
213 
214  /******************************************************************/
215  std::cout << std::endl << "Testing compressed(CSR) lhs * transposed dense rhs:" << std::endl;
216  C.clear();
217  C = viennacl::linalg::prod(compressed_A, viennacl::trans(B2));
218 
219  for (std::size_t i=0; i<temp.size(); ++i)
220  for (std::size_t j=0; j<temp[i].size(); ++j)
221  temp[i][j] = 0;
222  viennacl::copy(C, temp);
223  retVal = check_matrices(std_C, temp, epsilon);
224  if (retVal != EXIT_SUCCESS)
225  {
226  std::cerr << "Test failed!" << std::endl;
227  return retVal;
228  }
229 
230  /******************************************************************/
231  std::cout << "Testing compressed(ELL) lhs * transposed dense rhs" << std::endl;
232  C.clear();
233  C = viennacl::linalg::prod(ell_A, viennacl::trans(B2));
234 
235  for (std::size_t i=0; i<temp.size(); ++i)
236  for (std::size_t j=0; j<temp[i].size(); ++j)
237  temp[i][j] = 0;
238  viennacl::copy(C, temp);
239  retVal = check_matrices(std_C, temp, epsilon);
240  if (retVal != EXIT_SUCCESS)
241  {
242  std::cerr << "Test failed!" << std::endl;
243  return retVal;
244  }
245 
246  /******************************************************************/
247  std::cout << "Testing compressed(COO) lhs * transposed dense rhs" << std::endl;
248  C.clear();
249  C = viennacl::linalg::prod(coo_A, viennacl::trans(B2));
250 
251  for (std::size_t i=0; i<temp.size(); ++i)
252  for (std::size_t j=0; j<temp[i].size(); ++j)
253  temp[i][j] = 0;
254  viennacl::copy(C, temp);
255  retVal = check_matrices(std_C, temp, epsilon);
256  if (retVal != EXIT_SUCCESS)
257  {
258  std::cerr << "Test failed!" << std::endl;
259  return retVal;
260  }
261 
262  /******************************************************************/
263 
264  std::cout << "Testing compressed(HYB) lhs * transposed dense rhs" << std::endl;
265  C.clear();
266  C = viennacl::linalg::prod(hyb_A, viennacl::trans(B2));
267 
268  for (std::size_t i=0; i<temp.size(); ++i)
269  for (std::size_t j=0; j<temp[i].size(); ++j)
270  temp[i][j] = 0;
271  viennacl::copy(C, temp);
272  retVal = check_matrices(std_C, temp, epsilon);
273  if (retVal != EXIT_SUCCESS)
274  {
275  std::cerr << "Test failed!" << std::endl;
276  return retVal;
277  }
278 
279  /******************************************************************/
280  if (retVal == EXIT_SUCCESS) {
281  std::cout << "Tests passed successfully" << std::endl;
282  }
283 
284  return retVal;
285 }
286 
287 //
288 // -------------------------------------------------------------
289 //
290 int main()
291 {
292  std::cout << std::endl;
293  std::cout << "----------------------------------------------" << std::endl;
294  std::cout << "----------------------------------------------" << std::endl;
295  std::cout << "## Test :: Sparse-Dense Matrix Multiplication" << std::endl;
296  std::cout << "----------------------------------------------" << std::endl;
297  std::cout << "----------------------------------------------" << std::endl;
298  std::cout << std::endl;
299 
300  int retval = EXIT_SUCCESS;
301 
302  std::cout << std::endl;
303  std::cout << "----------------------------------------------" << std::endl;
304  std::cout << std::endl;
305  {
306  typedef float NumericT;
307  NumericT epsilon = static_cast<NumericT>(1E-4);
308  std::cout << "# Testing setup:" << std::endl;
309  std::cout << " eps: " << epsilon << std::endl;
310  std::cout << " numeric: float" << std::endl;
311  std::cout << " layout: row-major, row-major" << std::endl;
312  retval = test<NumericT, viennacl::row_major, viennacl::row_major>(epsilon);
313  if ( retval == EXIT_SUCCESS )
314  std::cout << "# Test passed" << std::endl;
315  else
316  return retval;
317 
318  std::cout << "# Testing setup:" << std::endl;
319  std::cout << " eps: " << epsilon << std::endl;
320  std::cout << " numeric: float" << std::endl;
321  std::cout << " layout: row-major, column-major" << std::endl;
322  retval = test<NumericT, viennacl::row_major, viennacl::column_major>(epsilon);
323  if ( retval == EXIT_SUCCESS )
324  std::cout << "# Test passed" << std::endl;
325  else
326  return retval;
327 
328  std::cout << "# Testing setup:" << std::endl;
329  std::cout << " eps: " << epsilon << std::endl;
330  std::cout << " numeric: float" << std::endl;
331  std::cout << " layout: column-major, row-major" << std::endl;
332  retval = test<NumericT, viennacl::column_major, viennacl::row_major>(epsilon);
333  if ( retval == EXIT_SUCCESS )
334  std::cout << "# Test passed" << std::endl;
335  else
336  return retval;
337 
338  std::cout << "# Testing setup:" << std::endl;
339  std::cout << " eps: " << epsilon << std::endl;
340  std::cout << " numeric: float" << std::endl;
341  std::cout << " layout: column-major, column-major" << std::endl;
342  retval = test<NumericT, viennacl::column_major, viennacl::column_major>(epsilon);
343  if ( retval == EXIT_SUCCESS )
344  std::cout << "# Test passed" << std::endl;
345  else
346  return retval;
347 
348  }
349  std::cout << std::endl;
350  std::cout << "----------------------------------------------" << std::endl;
351  std::cout << std::endl;
352 
353 #ifdef VIENNACL_WITH_OPENCL
355 #endif
356  {
357  {
358  typedef double NumericT;
359  NumericT epsilon = 1.0E-12;
360  std::cout << "# Testing setup:" << std::endl;
361  std::cout << " eps: " << epsilon << std::endl;
362  std::cout << " numeric: double" << std::endl;
363  std::cout << " layout: row-major, row-major" << std::endl;
364  retval = test<NumericT, viennacl::row_major, viennacl::row_major>(epsilon);
365  if ( retval == EXIT_SUCCESS )
366  std::cout << "# Test passed" << std::endl;
367  else
368  return retval;
369 
370  std::cout << "# Testing setup:" << std::endl;
371  std::cout << " eps: " << epsilon << std::endl;
372  std::cout << " numeric: double" << std::endl;
373  std::cout << " layout: row-major, column-major" << std::endl;
374  retval = test<NumericT, viennacl::row_major, viennacl::column_major>(epsilon);
375  if ( retval == EXIT_SUCCESS )
376  std::cout << "# Test passed" << std::endl;
377  else
378  return retval;
379 
380  std::cout << "# Testing setup:" << std::endl;
381  std::cout << " eps: " << epsilon << std::endl;
382  std::cout << " numeric: double" << std::endl;
383  std::cout << " layout: column-major, row-major" << std::endl;
384  retval = test<NumericT, viennacl::column_major, viennacl::row_major>(epsilon);
385  if ( retval == EXIT_SUCCESS )
386  std::cout << "# Test passed" << std::endl;
387  else
388  return retval;
389 
390  std::cout << "# Testing setup:" << std::endl;
391  std::cout << " eps: " << epsilon << std::endl;
392  std::cout << " numeric: double" << std::endl;
393  std::cout << " layout: column-major, column-major" << std::endl;
394  retval = test<NumericT, viennacl::column_major, viennacl::column_major>(epsilon);
395  if ( retval == EXIT_SUCCESS )
396  std::cout << "# Test passed" << std::endl;
397  else
398  return retval;
399  }
400  std::cout << std::endl;
401  std::cout << "----------------------------------------------" << std::endl;
402  std::cout << std::endl;
403  }
404 #ifdef VIENNACL_WITH_OPENCL
405  else
406  std::cout << "No double precision support, skipping test..." << std::endl;
407 #endif
408 
409 
410  std::cout << std::endl;
411  std::cout << "------- Test completed --------" << std::endl;
412  std::cout << std::endl;
413 
414  return retval;
415 }
416 
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.
Generic interface for the l^2-norm. See viennacl/linalg/vector_operations.hpp for implementations...
viennacl::enable_if< viennacl::is_any_sparse_matrix< M1 >::value, matrix_expression< const M1, const M1, op_trans > >::type trans(const M1 &mat)
Returns an expression template class representing a transposed matrix.
Generic interface for matrix-vector and matrix-matrix products. See viennacl/linalg/vector_operations...
Implementation of the dense matrix class.
int check_matrices(std::vector< std::vector< NumericT > > const &ref_mat, std::vector< std::vector< NumericT > > const &mat, NumericT eps)
Definition: spmdm.cpp:49
A dense matrix class.
Definition: forwards.h:375
int main()
Definition: spmdm.cpp:290
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
int test(NumericT epsilon)
Definition: spmdm.cpp:95
Implementation of the hyb_matrix class.
VectorT prod(std::vector< std::vector< T, A1 >, A2 > const &matrix, VectorT const &vector)
Definition: prod.hpp:102
vcl_size_t size(VectorType const &vec)
Generic routine for obtaining the size of a vector (ViennaCL, uBLAS, etc.)
Definition: size.hpp:239
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 clear()
Resets all entries to zero.
Implementation of the compressed_matrix class.
void compute_reference_result(std::vector< std::map< IndexT, NumericT > > const &A, std::vector< std::vector< NumericT > > const &B, std::vector< std::vector< NumericT > > &C)
Definition: spmdm.cpp:76
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.
Implementations of dense direct solvers are found here.
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) ...
A small collection of sequential random number generators.
long read_matrix_market_file(MatrixT &mat, const char *file, long index_base=1)
Reads a sparse matrix from a file (MatrixMarket format)
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...