ViennaCL - The Vienna Computing Library  1.6.2
Free open-source GPU-accelerated linear algebra and solver library.
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
cg.hpp
Go to the documentation of this file.
1 #ifndef VIENNACL_LINALG_CG_HPP_
2 #define VIENNACL_LINALG_CG_HPP_
3 
4 /* =========================================================================
5  Copyright (c) 2010-2014, 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 PDF manual)
17 
18  License: MIT (X11), see file LICENSE in the base directory
19 ============================================================================= */
20 
25 #include <vector>
26 #include <map>
27 #include <cmath>
28 #include <numeric>
29 
30 #include "viennacl/forwards.h"
31 #include "viennacl/tools/tools.hpp"
32 #include "viennacl/linalg/ilu.hpp"
33 #include "viennacl/linalg/prod.hpp"
37 #include "viennacl/traits/size.hpp"
40 
41 namespace viennacl
42 {
43 namespace linalg
44 {
45 
48 class cg_tag
49 {
50 public:
56  cg_tag(double tol = 1e-8, unsigned int max_iterations = 300) : tol_(tol), iterations_(max_iterations) {}
57 
59  double tolerance() const { return tol_; }
61  unsigned int max_iterations() const { return iterations_; }
62 
64  unsigned int iters() const { return iters_taken_; }
65  void iters(unsigned int i) const { iters_taken_ = i; }
66 
68  double error() const { return last_error_; }
70  void error(double e) const { last_error_ = e; }
71 
72 
73 private:
74  double tol_;
75  unsigned int iterations_;
76 
77  //return values from solver
78  mutable unsigned int iters_taken_;
79  mutable double last_error_;
80 };
81 
82 namespace detail
83 {
84 
86  template<typename VectorT, typename PreconditionerT>
87  class z_handler{
88  public:
89  z_handler(VectorT & residual) : z_(residual){ }
90  VectorT & get() { return z_; }
91  private:
92  VectorT z_;
93  };
94 
95  template<typename VectorT>
96  class z_handler<VectorT, viennacl::linalg::no_precond>{
97  public:
98  z_handler(VectorT & residual) : presidual_(&residual){ }
99  VectorT & get() { return *presidual_; }
100  private:
101  VectorT * presidual_;
102  };
103 
104 }
105 
106 namespace detail
107 {
108 
118  //template<typename MatrixType, typename ScalarType>
119  template<typename MatrixT, typename NumericT>
120  viennacl::vector<NumericT> pipelined_solve(MatrixT const & A, //MatrixType const & A,
121  viennacl::vector<NumericT> const & rhs,
122  cg_tag const & tag,
124  {
125  typedef typename viennacl::vector<NumericT>::difference_type difference_type;
126 
127  viennacl::vector<NumericT> result(rhs);
128  viennacl::traits::clear(result);
129 
130  viennacl::vector<NumericT> residual(rhs);
133  viennacl::vector<NumericT> inner_prod_buffer = viennacl::zero_vector<NumericT>(3*256, viennacl::traits::context(rhs)); // temporary buffer
134  std::vector<NumericT> host_inner_prod_buffer(inner_prod_buffer.size());
135  vcl_size_t buffer_size_per_vector = inner_prod_buffer.size() / 3;
136  difference_type buffer_offset_per_vector = static_cast<difference_type>(buffer_size_per_vector);
137 
138  NumericT norm_rhs_squared = viennacl::linalg::norm_2(residual); norm_rhs_squared *= norm_rhs_squared;
139 
140  if (!norm_rhs_squared) //check for early convergence of A*x = 0
141  return result;
142 
143  NumericT inner_prod_rr = norm_rhs_squared;
144  NumericT alpha = inner_prod_rr / viennacl::linalg::inner_prod(p, Ap);
145  NumericT beta = viennacl::linalg::norm_2(Ap); beta = (alpha * alpha * beta * beta - inner_prod_rr) / inner_prod_rr;
146  NumericT inner_prod_ApAp = 0;
147  NumericT inner_prod_pAp = 0;
148 
149  for (unsigned int i = 0; i < tag.max_iterations(); ++i)
150  {
151  tag.iters(i+1);
152 
153  viennacl::linalg::pipelined_cg_vector_update(result, alpha, p, residual, Ap, beta, inner_prod_buffer);
154  viennacl::linalg::pipelined_cg_prod(A, p, Ap, inner_prod_buffer);
155 
156  // bring back the partial results to the host:
157  viennacl::fast_copy(inner_prod_buffer.begin(), inner_prod_buffer.end(), host_inner_prod_buffer.begin());
158 
159  inner_prod_rr = std::accumulate(host_inner_prod_buffer.begin(), host_inner_prod_buffer.begin() + buffer_offset_per_vector, NumericT(0));
160  inner_prod_ApAp = std::accumulate(host_inner_prod_buffer.begin() + buffer_offset_per_vector, host_inner_prod_buffer.begin() + 2 * buffer_offset_per_vector, NumericT(0));
161  inner_prod_pAp = std::accumulate(host_inner_prod_buffer.begin() + 2 * buffer_offset_per_vector, host_inner_prod_buffer.begin() + 3 * buffer_offset_per_vector, NumericT(0));
162 
163  if (std::fabs(inner_prod_rr / norm_rhs_squared) < tag.tolerance() * tag.tolerance()) //squared norms involved here
164  break;
165 
166  alpha = inner_prod_rr / inner_prod_pAp;
167  beta = (alpha*alpha*inner_prod_ApAp - inner_prod_rr) / inner_prod_rr;
168  }
169 
170  //store last error estimate:
171  tag.error(std::sqrt(std::fabs(inner_prod_rr) / norm_rhs_squared));
172 
173  return result;
174  }
175 }
176 
177 // compressed_matrix
178 
180 template<typename NumericT>
183  cg_tag const & tag,
185 {
187 }
188 
190 template<typename NumericT>
192  viennacl::vector<NumericT> const & rhs,
193  cg_tag const & tag,
195 {
197 }
198 
200 template<typename NumericT>
203  cg_tag const & tag,
205 {
207 }
208 
210 template<typename NumericT>
213  cg_tag const & tag,
215 {
217 }
218 
219 // coordinate_matrix
220 
222 template<typename NumericT>
225  cg_tag const & tag,
227 {
229 }
230 
232 template<typename NumericT>
234  viennacl::vector<NumericT> const & rhs,
235  cg_tag const & tag,
237 {
239 }
240 
242 template<typename NumericT>
245  cg_tag const & tag,
247 {
249 }
250 
252 template<typename NumericT>
255  cg_tag const & tag,
257 {
259 }
260 
261 // ell_matrix
262 
264 template<typename NumericT>
267  cg_tag const & tag,
269 {
271 }
272 
274 template<typename NumericT>
276  viennacl::vector<NumericT> const & rhs,
277  cg_tag const & tag,
279 {
281 }
282 
284 template<typename NumericT>
287  cg_tag const & tag,
289 {
291 }
292 
294 template<typename NumericT>
297  cg_tag const & tag,
299 {
301 }
302 
303 
304 
305 // sliced_ell_matrix
306 
308 template<typename NumericT>
311  cg_tag const & tag,
313 {
315 }
316 
318 template<typename NumericT>
320  viennacl::vector<NumericT> const & rhs,
321  cg_tag const & tag,
323 {
325 }
326 
328 template<typename NumericT>
331  cg_tag const & tag,
333 {
335 }
336 
338 template<typename NumericT>
341  cg_tag const & tag,
343 {
345 }
346 
347 
348 // hyb_matrix
349 
351 template<typename NumericT>
354  cg_tag const & tag,
356 {
358 }
359 
361 template<typename NumericT>
363  viennacl::vector<NumericT> const & rhs,
364  cg_tag const & tag,
366 {
368 }
369 
371 template<typename NumericT>
374  cg_tag const & tag,
376 {
378 }
379 
381 template<typename NumericT>
384  cg_tag const & tag,
386 {
388 }
389 
390 
391 
392 
393 
394 
395 
396 
407 template<typename MatrixT, typename VectorT, typename PreconditionerT>
408 VectorT solve(MatrixT const & matrix, VectorT const & rhs, cg_tag const & tag, PreconditionerT const & precond)
409 {
410  typedef typename viennacl::result_of::value_type<VectorT>::type NumericType;
411  typedef typename viennacl::result_of::cpu_value_type<NumericType>::type CPU_NumericType;
412 
413  VectorT result = rhs;
414  viennacl::traits::clear(result);
415 
416  VectorT residual = rhs;
417  VectorT tmp = rhs;
419  VectorT & z = zhandler.get();
420 
421  precond.apply(z);
422  VectorT p = z;
423 
424  CPU_NumericType ip_rr = viennacl::linalg::inner_prod(residual, z);
425  CPU_NumericType alpha;
426  CPU_NumericType new_ip_rr = 0;
427  CPU_NumericType beta;
428  CPU_NumericType norm_rhs_squared = ip_rr;
429  CPU_NumericType new_ipp_rr_over_norm_rhs;
430 
431  if (norm_rhs_squared <= 0) //solution is zero if RHS norm is zero
432  return result;
433 
434  for (unsigned int i = 0; i < tag.max_iterations(); ++i)
435  {
436  tag.iters(i+1);
437  tmp = viennacl::linalg::prod(matrix, p);
438 
439  alpha = ip_rr / viennacl::linalg::inner_prod(tmp, p);
440 
441  result += alpha * p;
442  residual -= alpha * tmp;
443  z = residual;
444  precond.apply(z);
445 
446  if (&residual==&z)
447  new_ip_rr = std::pow(viennacl::linalg::norm_2(residual),2);
448  else
449  new_ip_rr = viennacl::linalg::inner_prod(residual, z);
450 
451  new_ipp_rr_over_norm_rhs = new_ip_rr / norm_rhs_squared;
452  if (std::fabs(new_ipp_rr_over_norm_rhs) < tag.tolerance() * tag.tolerance()) //squared norms involved here
453  break;
454 
455  beta = new_ip_rr / ip_rr;
456  ip_rr = new_ip_rr;
457 
458  p = z + beta*p;
459  }
460 
461  //store last error estimate:
462  tag.error(std::sqrt(std::fabs(new_ip_rr / norm_rhs_squared)));
463 
464  return result;
465 }
466 
467 template<typename MatrixT, typename VectorT>
468 VectorT solve(MatrixT const & matrix, VectorT const & rhs, cg_tag const & tag)
469 {
470  return solve(matrix, rhs, tag, viennacl::linalg::no_precond());
471 }
472 
473 }
474 }
475 
476 #endif
Sparse matrix class using a hybrid format composed of the ELL and CSR format for storing the nonzeros...
Definition: forwards.h:405
T norm_2(std::vector< T, A > const &v1)
Definition: norm_2.hpp:86
viennacl::vector< NumericT > pipelined_solve(MatrixT const &A, viennacl::vector_base< NumericT > const &rhs, bicgstab_tag const &tag, viennacl::linalg::no_precond)
Implementation of a pipelined stabilized Bi-conjugate gradient solver.
Definition: bicgstab.hpp:91
Generic interface for the l^2-norm. See viennacl/linalg/vector_operations.hpp for implementations...
cg_tag(double tol=1e-8, unsigned int max_iterations=300)
The constructor.
Definition: cg.hpp:56
Generic size and resize functionality for different vector and matrix types.
Generic interface for matrix-vector and matrix-matrix products. See viennacl/linalg/vector_operations...
Various little tools used here and there in ViennaCL.
double tolerance() const
Returns the relative tolerance.
Definition: cg.hpp:59
handles the no_precond case at minimal overhead
Definition: cg.hpp:87
void clear(VectorType &vec)
Generic routine for setting all entries of a vector to zero. This is the version for non-ViennaCL obj...
Definition: clear.hpp:57
This file provides the forward declarations for the main types used within ViennaCL.
A dense matrix class.
Definition: forwards.h:374
viennacl::enable_if< viennacl::is_stl< typename viennacl::traits::tag_of< VectorT1 >::type >::value, typename VectorT1::value_type >::type inner_prod(VectorT1 const &v1, VectorT2 const &v2)
Definition: inner_prod.hpp:89
void pipelined_cg_vector_update(vector_base< NumericT > &result, NumericT alpha, vector_base< NumericT > &p, vector_base< NumericT > &r, vector_base< NumericT > const &Ap, NumericT beta, vector_base< NumericT > &inner_prod_buffer)
Performs a joint vector update operation needed for an efficient pipelined CG algorithm.
unsigned int iters() const
Return the number of solver iterations:
Definition: cg.hpp:64
Generic interface for the computation of inner products. See viennacl/linalg/vector_operations.hpp for implementations.
void pipelined_cg_prod(MatrixT const &A, vector_base< NumericT > const &p, vector_base< NumericT > &Ap, vector_base< NumericT > &inner_prod_buffer)
Performs a joint vector update operation needed for an efficient pipelined CG algorithm.
viennacl::vector< NumericT > solve(viennacl::compressed_matrix< NumericT > const &A, viennacl::vector_base< NumericT > const &rhs, bicgstab_tag const &tag, viennacl::linalg::no_precond)
Overload for the pipelined BiCGStab implementation for the ViennaCL sparse matrix types...
Definition: bicgstab.hpp:209
unsigned int max_iterations() const
Returns the maximum number of iterations.
Definition: cg.hpp:61
VectorT prod(std::vector< std::vector< T, A1 >, A2 > const &matrix, VectorT const &vector)
Definition: prod.hpp:91
Class for representing non-strided subvectors of a bigger vector x.
Definition: forwards.h:433
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
A tag class representing the use of no preconditioner.
Definition: forwards.h:833
Implementations of incomplete factorization preconditioners. Convenience header file.
base_type::difference_type difference_type
Definition: vector.hpp:943
Sparse matrix class using the sliced ELLPACK with parameters C, .
Definition: forwards.h:402
Class for representing strided subvectors of a bigger vector x.
Definition: forwards.h:436
std::size_t vcl_size_t
Definition: forwards.h:74
Generic clear functionality for different vector and matrix types.
T::ERROR_CANNOT_DEDUCE_CPU_SCALAR_TYPE_FOR_T type
Definition: result_of.hpp:238
double error() const
Returns the estimated relative error at the end of the solver run.
Definition: cg.hpp:68
z_handler(VectorT &residual)
Definition: cg.hpp:89
Implementations of specialized routines for the iterative solvers.
viennacl::context context(T const &t)
Returns an ID for the currently active memory domain of an object.
Definition: context.hpp:40
void iters(unsigned int i) const
Definition: cg.hpp:65
void error(double e) const
Sets the estimated relative error at the end of the solver run.
Definition: cg.hpp:70
size_type size() const
Returns the length of the vector (cf. std::vector)
Definition: vector_def.hpp:118
A tag for the conjugate gradient Used for supplying solver parameters and for dispatching the solve()...
Definition: cg.hpp:48
iterator end()
Returns an iterator pointing to the end of the vector (STL like)
Definition: vector.hpp:834
A collection of compile time type deductions.
A sparse square matrix, where entries are stored as triplets (i,j, val), where i and j are the row an...
void fast_copy(const const_vector_iterator< SCALARTYPE, ALIGNMENT > &gpu_begin, const const_vector_iterator< SCALARTYPE, ALIGNMENT > &gpu_end, CPU_ITERATOR cpu_begin)