ViennaCL - The Vienna Computing Library: tests/src/spmdm.cpp Source File

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"
37 #include "viennacl/linalg/direct_solve.hpp"
38 #include "viennacl/compressed_matrix.hpp"
39 #include "viennacl/coordinate_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
44 #include "viennacl/io/matrix_market.hpp"
45 #include "viennacl/tools/random.hpp"
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
99 viennacl::tools::uniform_random_numbers<NumericT> randomNumber;
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
114 viennacl::compressed_matrix<NumericT> compressed_A;
115 viennacl::ell_matrix<NumericT> ell_A;
116 viennacl::coordinate_matrix<NumericT> coo_A;
117 viennacl::hyb_matrix<NumericT> hyb_A;
118
119 std::vector<std::vector<NumericT> > std_C(std_A.size(), std::vector<NumericT>(cols_rhs));
120 viennacl::matrix<NumericT, ResultLayoutT> C;
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);
129 viennacl::matrix<NumericT, FactorLayoutT> B2;
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
354 if ( viennacl::ocl::current_device().double_support() )
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
viennacl::hyb_matrix
Sparse matrix class using a hybrid format composed of the ELL and CSR format for storing the nonzeros...
Definition: forwards.h:406
matrix_market.hpp
A reader and writer for the matrix market format is implemented here.
norm_2.hpp
Generic interface for the l^2-norm. See viennacl/linalg/vector_operations.hpp for implementations...
viennacl::trans
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.
Definition: sparse_matrix_operations.hpp:376
prod.hpp
Generic interface for matrix-vector and matrix-matrix products. See viennacl/linalg/vector_operations...
matrix.hpp
Implementation of the dense matrix class.
check_matrices
int check_matrices(std::vector< std::vector< NumericT > > const &ref_mat, std::vector< std::vector< NumericT > > const &mat, NumericT eps)
Definition: spmdm.cpp:49
viennacl::matrix
A dense matrix class.
Definition: forwards.h:375
main
int main()
Definition: spmdm.cpp:290
viennacl::linalg::detail::max
T max(const T &lhs, const T &rhs)
Maximum.
Definition: util.hpp:59
viennacl::ocl::current_device
viennacl::ocl::device const & current_device()
Convenience function for returning the active device in the current context.
Definition: backend.hpp:351
coordinate_matrix.hpp
Implementation of the coordinate_matrix class.
NumericT
float NumericT
Definition: bisect.cpp:40
test
int test(NumericT epsilon)
Definition: spmdm.cpp:95
hyb_matrix.hpp
Implementation of the hyb_matrix class.
viennacl::linalg::prod
VectorT prod(std::vector< std::vector< T, A1 >, A2 > const &matrix, VectorT const &vector)
Definition: prod.hpp:102
viennacl::traits::size
vcl_size_t size(VectorType const &vec)
Generic routine for obtaining the size of a vector (ViennaCL, uBLAS, etc.)
Definition: size.hpp:239
viennacl::tools::uniform_random_numbers
Random number generator for returning uniformly distributed values in the closed interval [0...
Definition: random.hpp:44
viennacl::ell_matrix
Sparse matrix class using the ELLPACK format for storing the nonzeros.
Definition: ell_matrix.hpp:53
viennacl::matrix_base< NumericT >::clear
void clear()
Resets all entries to zero.
compressed_matrix.hpp
Implementation of the compressed_matrix class.
compute_reference_result
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
viennacl::ocl::device::double_support
bool double_support() const
ViennaCL convenience function: Returns true if the device supports double precision.
Definition: device.hpp:956
ell_matrix.hpp
Implementation of the ell_matrix class.
direct_solve.hpp
Implementations of dense direct solvers are found here.
vector.hpp
The vector type with operator-overloads and proxy classes is defined here. Linear algebra operations ...
viennacl::copy
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) ...
Definition: circulant_matrix.hpp:150
random.hpp
A small collection of sequential random number generators.
viennacl::compressed_matrix< NumericT >
viennacl::io::read_matrix_market_file
long read_matrix_market_file(MatrixT &mat, const char *file, long index_base=1)
Reads a sparse matrix from a file (MatrixMarket format)
Definition: matrix_market.hpp:339
scalar.hpp
Implementation of the ViennaCL scalar class.
viennacl::coordinate_matrix
A sparse square matrix, where entries are stored as triplets (i,j, val), where i and j are the row an...
Definition: coordinate_matrix.hpp:186