ViennaCL - The Vienna Computing Library  1.6.1
Free open-source GPU-accelerated linear algebra and solver library.
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>
97  public:
98  z_handler(VectorT & residual) : presidual_(&residual){ }
99  VectorT & get() { return *presidual_; }
100  private:
101  VectorT * presidual_;
102  };
103 
104 }
105 
115 //template<typename MatrixType, typename ScalarType>
116 template<typename MatrixT, typename NumericT>
117 viennacl::vector<NumericT> solve(MatrixT const & A, //MatrixType const & A,
118  viennacl::vector<NumericT> const & rhs,
119  cg_tag const & tag,
121 {
122  typedef typename viennacl::vector<NumericT>::difference_type difference_type;
123 
124  viennacl::vector<NumericT> result(rhs);
125  viennacl::traits::clear(result);
126 
127  viennacl::vector<NumericT> residual(rhs);
130  viennacl::vector<NumericT> inner_prod_buffer = viennacl::zero_vector<NumericT>(3*256, viennacl::traits::context(rhs)); // temporary buffer
131  std::vector<NumericT> host_inner_prod_buffer(inner_prod_buffer.size());
132  vcl_size_t buffer_size_per_vector = inner_prod_buffer.size() / 3;
133  difference_type buffer_offset_per_vector = static_cast<difference_type>(buffer_size_per_vector);
134 
135  NumericT norm_rhs_squared = viennacl::linalg::norm_2(residual); norm_rhs_squared *= norm_rhs_squared;
136 
137  if (!norm_rhs_squared) //check for early convergence of A*x = 0
138  return result;
139 
140  NumericT inner_prod_rr = norm_rhs_squared;
141  NumericT alpha = inner_prod_rr / viennacl::linalg::inner_prod(p, Ap);
142  NumericT beta = viennacl::linalg::norm_2(Ap); beta = (alpha * alpha * beta * beta - inner_prod_rr) / inner_prod_rr;
143  NumericT inner_prod_ApAp = 0;
144  NumericT inner_prod_pAp = 0;
145 
146  for (unsigned int i = 0; i < tag.max_iterations(); ++i)
147  {
148  tag.iters(i+1);
149 
150  viennacl::linalg::pipelined_cg_vector_update(result, alpha, p, residual, Ap, beta, inner_prod_buffer);
151  viennacl::linalg::pipelined_cg_prod(A, p, Ap, inner_prod_buffer);
152 
153  // bring back the partial results to the host:
154  viennacl::fast_copy(inner_prod_buffer.begin(), inner_prod_buffer.end(), host_inner_prod_buffer.begin());
155 
156  inner_prod_rr = std::accumulate(host_inner_prod_buffer.begin(), host_inner_prod_buffer.begin() + buffer_offset_per_vector, NumericT(0));
157  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));
158  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));
159 
160  if (std::fabs(inner_prod_rr / norm_rhs_squared) < tag.tolerance() * tag.tolerance()) //squared norms involved here
161  break;
162 
163  alpha = inner_prod_rr / inner_prod_pAp;
164  beta = (alpha*alpha*inner_prod_ApAp - inner_prod_rr) / inner_prod_rr;
165  }
166 
167  //store last error estimate:
168  tag.error(std::sqrt(std::fabs(inner_prod_rr) / norm_rhs_squared));
169 
170  return result;
171 }
172 
183 template<typename MatrixT, typename VectorT, typename PreconditionerT>
184 VectorT solve(MatrixT const & matrix, VectorT const & rhs, cg_tag const & tag, PreconditionerT const & precond)
185 {
186  typedef typename viennacl::result_of::value_type<VectorT>::type NumericType;
187  typedef typename viennacl::result_of::cpu_value_type<NumericType>::type CPU_NumericType;
188 
189  VectorT result = rhs;
190  viennacl::traits::clear(result);
191 
192  VectorT residual = rhs;
193  VectorT tmp = rhs;
195  VectorT & z = zhandler.get();
196 
197  precond.apply(z);
198  VectorT p = z;
199 
200  CPU_NumericType ip_rr = viennacl::linalg::inner_prod(residual, z);
201  CPU_NumericType alpha;
202  CPU_NumericType new_ip_rr = 0;
203  CPU_NumericType beta;
204  CPU_NumericType norm_rhs_squared = ip_rr;
205  CPU_NumericType new_ipp_rr_over_norm_rhs;
206 
207  if (norm_rhs_squared <= 0) //solution is zero if RHS norm is zero
208  return result;
209 
210  for (unsigned int i = 0; i < tag.max_iterations(); ++i)
211  {
212  tag.iters(i+1);
213  tmp = viennacl::linalg::prod(matrix, p);
214 
215  alpha = ip_rr / viennacl::linalg::inner_prod(tmp, p);
216 
217  result += alpha * p;
218  residual -= alpha * tmp;
219  z = residual;
220  precond.apply(z);
221 
222  if (&residual==&z)
223  new_ip_rr = std::pow(viennacl::linalg::norm_2(residual),2);
224  else
225  new_ip_rr = viennacl::linalg::inner_prod(residual, z);
226 
227  new_ipp_rr_over_norm_rhs = new_ip_rr / norm_rhs_squared;
228  if (std::fabs(new_ipp_rr_over_norm_rhs) < tag.tolerance() * tag.tolerance()) //squared norms involved here
229  break;
230 
231  beta = new_ip_rr / ip_rr;
232  ip_rr = new_ip_rr;
233 
234  p = z + beta*p;
235  }
236 
237  //store last error estimate:
238  tag.error(std::sqrt(std::fabs(new_ip_rr / norm_rhs_squared)));
239 
240  return result;
241 }
242 
243 template<typename MatrixT, typename VectorT>
244 VectorT solve(MatrixT const & matrix, VectorT const & rhs, cg_tag const & tag)
245 {
246  return solve(matrix, rhs, tag, viennacl::linalg::no_precond());
247 }
248 
249 }
250 }
251 
252 #endif
T norm_2(std::vector< T, A > const &v1)
Definition: norm_2.hpp:86
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.
base_type::difference_type difference_type
Definition: vector.hpp:943
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.
Main namespace in ViennaCL. Holds all the basic types such as vector, matrix, etc. and defines operations upon them.
Definition: cpu_ram.hpp:29
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
Definition: blas3.hpp:36
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.
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.
viennacl::vector< NumericT > 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:88
void fast_copy(const const_vector_iterator< SCALARTYPE, ALIGNMENT > &gpu_begin, const const_vector_iterator< SCALARTYPE, ALIGNMENT > &gpu_end, CPU_ITERATOR cpu_begin)