Amesos2 - Direct Sparse Solver Interfaces  Version of the Day
Amesos2_cuSOLVER_def.hpp
1 // @HEADER
2 //
3 // ***********************************************************************
4 //
5 // Amesos2: Templated Direct Sparse Solver Package
6 // Copyright 2011 Sandia Corporation
7 //
8 // Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
9 // the U.S. Government retains certain rights in this software.
10 //
11 // Redistribution and use in source and binary forms, with or without
12 // modification, are permitted provided that the following conditions are
13 // met:
14 //
15 // 1. Redistributions of source code must retain the above copyright
16 // notice, this list of conditions and the following disclaimer.
17 //
18 // 2. Redistributions in binary form must reproduce the above copyright
19 // notice, this list of conditions and the following disclaimer in the
20 // documentation and/or other materials provided with the distribution.
21 //
22 // 3. Neither the name of the Corporation nor the names of the
23 // contributors may be used to endorse or promote products derived from
24 // this software without specific prior written permission.
25 //
26 // THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
27 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
30 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
31 // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
32 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
33 // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
34 // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
35 // NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
36 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37 //
38 // Questions? Contact Michael A. Heroux (maherou@sandia.gov)
39 //
40 // ***********************************************************************
41 //
42 // @HEADER
43 
44 #ifndef AMESOS2_CUSOLVER_DEF_HPP
45 #define AMESOS2_CUSOLVER_DEF_HPP
46 
47 #include <Teuchos_Tuple.hpp>
48 #include <Teuchos_ParameterList.hpp>
49 #include <Teuchos_StandardParameterEntryValidators.hpp>
50 
52 #include "Amesos2_cuSOLVER_decl.hpp"
53 
54 namespace Amesos2 {
55 
56 template <class Matrix, class Vector>
58  Teuchos::RCP<const Matrix> A,
59  Teuchos::RCP<Vector> X,
60  Teuchos::RCP<const Vector> B )
61  : SolverCore<Amesos2::cuSOLVER,Matrix,Vector>(A, X, B)
62 {
63  auto status = cusolverSpCreate(&data_.handle);
64  TEUCHOS_TEST_FOR_EXCEPTION( status != CUSOLVER_STATUS_SUCCESS,
65  std::runtime_error, "cusolverSpCreate failed");
66 
67  status = cusolverSpCreateCsrcholInfo(&data_.chol_info);
68  TEUCHOS_TEST_FOR_EXCEPTION( status != CUSOLVER_STATUS_SUCCESS,
69  std::runtime_error, "cusolverSpCreateCsrcholInfo failed");
70 
71  auto sparse_status = cusparseCreateMatDescr(&data_.desc);
72  TEUCHOS_TEST_FOR_EXCEPTION( sparse_status != CUSPARSE_STATUS_SUCCESS,
73  std::runtime_error, "cusparseCreateMatDescr failed");
74 }
75 
76 template <class Matrix, class Vector>
78 {
79  cusparseDestroyMatDescr(data_.desc);
80  cusolverSpDestroyCsrcholInfo(data_.chol_info);
81  cusolverSpDestroy(data_.handle);
82 }
83 
84 template<class Matrix, class Vector>
85 int
87 {
88 #ifdef HAVE_AMESOS2_TIMERS
89  Teuchos::TimeMonitor preOrderTimer(this->timers_.preOrderTime_);
90 #endif
91  if(do_optimization()) {
92  this->matrixA_->returnRowPtr_kokkos_view(device_row_ptr_view_);
93  this->matrixA_->returnColInd_kokkos_view(device_cols_view_);
94 
95  // reorder to optimize cuSolver
96  if(data_.bReorder) {
97  Amesos2::Util::reorder(
98  device_row_ptr_view_, device_cols_view_,
99  device_perm_, device_peri_, sorted_nnz);
100  }
101  }
102 
103  return(0);
104 }
105 
106 template <class Matrix, class Vector>
107 int
109 {
110 #ifdef HAVE_AMESOS2_TIMERS
111  Teuchos::TimeMonitor symFactTimer(this->timers_.symFactTime_);
112 #endif
113 
114  int err = 0;
115  if ( this->root_ ) {
116  const int size = this->globalNumRows_;
117  const int nnz = device_cols_view_.size(); // reorder may have changed this
118  const int * colIdx = device_cols_view_.data();
119  const int * rowPtr = device_row_ptr_view_.data();
120  auto status = cusolverSpXcsrcholAnalysis(
121  data_.handle, size, nnz, data_.desc, rowPtr, colIdx, data_.chol_info);
122  err = (status != CUSOLVER_STATUS_SUCCESS) ? 1 : 0;
123  }
124 
125  Teuchos::broadcast(*(this->getComm()), 0, &err);
126  TEUCHOS_TEST_FOR_EXCEPTION(err != 0,
127  std::runtime_error, "Amesos2 cuSolver symbolic failed.");
128 
129  return err;
130 }
131 
132 template <class Matrix, class Vector>
133 int
135 {
136  int err = 0;
137  if(do_optimization()) { // just supporting one rank right now
138  this->matrixA_->returnValues_kokkos_view(device_nzvals_view_);
139 
140  // reorder to optimize cuSolver
141  if(data_.bReorder) {
142  // must have original row and cols - maybe cache this from 1st symbiolic setup
143  // this setup exists to support the refactor option
144  device_size_type_array orig_device_row_ptr_view;
145  device_ordinal_type_array orig_device_cols_view;
146  this->matrixA_->returnRowPtr_kokkos_view(orig_device_row_ptr_view);
147  this->matrixA_->returnColInd_kokkos_view(orig_device_cols_view);
148  Amesos2::Util::reorder_values(
149  device_nzvals_view_, orig_device_row_ptr_view, device_row_ptr_view_, orig_device_cols_view,
150  device_perm_, device_peri_, sorted_nnz);
151  }
152 
153  const int size = this->globalNumRows_;
154  const int nnz = device_cols_view_.size(); // reorder may have changed this
155  const cusolver_type * values = device_nzvals_view_.data();
156  const int * colIdx = device_cols_view_.data();
157  const int * rowPtr = device_row_ptr_view_.data();
158 
159  size_t internalDataInBytes, workspaceInBytes;
160  auto status = function_map::bufferInfo(data_.handle, size, nnz, data_.desc,
161  values, rowPtr, colIdx, data_.chol_info,
162  &internalDataInBytes, &workspaceInBytes);
163 
164  if(status == CUSOLVER_STATUS_SUCCESS) {
165  const size_t buffer_size = workspaceInBytes / sizeof(cusolver_type);
166  if(buffer_size > buffer_.extent(0)) {
167  buffer_ = device_value_type_array(
168  Kokkos::ViewAllocateWithoutInitializing("cusolver buf"), buffer_size);
169  }
170  status = function_map::numeric(data_.handle, size, nnz, data_.desc,
171  values, rowPtr, colIdx, data_.chol_info, buffer_.data());
172  }
173  err = (status != CUSOLVER_STATUS_SUCCESS) ? 1 : 0;
174  }
175 
176  Teuchos::broadcast(*(this->getComm()), 0, &err);
177  TEUCHOS_TEST_FOR_EXCEPTION(err != 0,
178  std::runtime_error, "Amesos2 cuSolver numeric failed.");
179 
180  return err;
181 }
182 
183 template <class Matrix, class Vector>
184 int
186  const Teuchos::Ptr<MultiVecAdapter<Vector> > X,
187  const Teuchos::Ptr<const MultiVecAdapter<Vector> > B) const
188 {
189  const global_size_type ld_rhs = this->root_ ? X->getGlobalLength() : 0;
190  const ordinal_type nrhs = X->getGlobalNumVectors();
191 
192  { // Get values from RHS B
193 #ifdef HAVE_AMESOS2_TIMERS
194  Teuchos::TimeMonitor mvConvTimer(this->timers_.vecConvTime_);
195  Teuchos::TimeMonitor redistTimer(this->timers_.vecRedistTime_);
196 #endif
197 
198  Util::get_1d_copy_helper_kokkos_view<MultiVecAdapter<Vector>,
199  device_solve_array_t>::do_get(B, this->bValues_, Teuchos::as<size_t>(ld_rhs),
200  ROOTED, this->rowIndexBase_);
201 
202  // In general we may want to write directly to the x space without a copy.
203  // So we 'get' x which may be a direct view assignment to the MV.
204  Util::get_1d_copy_helper_kokkos_view<MultiVecAdapter<Vector>,
205  device_solve_array_t>::do_get(X, this->xValues_, Teuchos::as<size_t>(ld_rhs),
206  ROOTED, this->rowIndexBase_);
207  }
208 
209  int err = 0;
210 
211  if ( this->root_ ) { // Do solve!
212 #ifdef HAVE_AMESOS2_TIMER
213  Teuchos::TimeMonitor solveTimer(this->timers_.solveTime_);
214 #endif
215 
216  const int size = this->globalNumRows_;
217 
218  if(data_.bReorder) {
219  Amesos2::Util::apply_reorder_permutation(
220  this->bValues_, this->permute_result_, this->device_perm_);
221  }
222  else {
223  this->permute_result_ = this->bValues_; // no permutation
224  }
225 
226  for(ordinal_type n = 0; n < nrhs; ++n) {
227  const cusolver_type * b = this->permute_result_.data() + n * size;
228  cusolver_type * x = this->xValues_.data() + n * size;
229  auto status = function_map::solve(
230  data_.handle, size, b, x, data_.chol_info, buffer_.data());
231  err = (status != CUSOLVER_STATUS_SUCCESS) ? 1 : 0;
232  if(err != 0) {
233  break;
234  }
235  }
236 
237  if(data_.bReorder && err == 0) {
238  Amesos2::Util::apply_reorder_permutation(
239  this->xValues_, this->permute_result_, this->device_peri_);
240  Kokkos::deep_copy(this->xValues_, this->permute_result_); // full copy since permute_result_ is reused
241  }
242  }
243 
244  /* Update X's global values */
245  {
246 #ifdef HAVE_AMESOS2_TIMERS
247  Teuchos::TimeMonitor redistTimer(this->timers_.vecRedistTime_);
248 #endif
249 
250  Util::template put_1d_data_helper_kokkos_view<
251  MultiVecAdapter<Vector>,device_solve_array_t>::do_put(X, xValues_,
252  Teuchos::as<size_t>(ld_rhs), ROOTED, this->rowIndexBase_);
253  }
254 
255  Teuchos::broadcast(*(this->getComm()), 0, &err);
256  TEUCHOS_TEST_FOR_EXCEPTION(err != 0,
257  std::runtime_error, "Amesos2 cuSolver solve failed.");
258 
259  return err;
260 }
261 
262 template <class Matrix, class Vector>
263 bool
265 {
266  return( this->matrixA_->getGlobalNumRows() == this->matrixA_->getGlobalNumCols() );
267 }
268 
269 template <class Matrix, class Vector>
270 void
271 cuSOLVER<Matrix,Vector>::setParameters_impl(const Teuchos::RCP<Teuchos::ParameterList> & parameterList )
272 {
273  using Teuchos::RCP;
274  using Teuchos::ParameterEntryValidator;
275 
276  RCP<const Teuchos::ParameterList> valid_params = getValidParameters_impl();
277 
278  if( parameterList->isParameter("Reorder") ){
279  RCP<const ParameterEntryValidator> reorder_validator = valid_params->getEntry("Reorder").validator();
280  parameterList->getEntry("Reorder").setValidator(reorder_validator);
281  }
282 
283  data_.bReorder = parameterList->get<bool>("Reorder", true);
284 }
285 
286 template <class Matrix, class Vector>
287 Teuchos::RCP<const Teuchos::ParameterList>
289 {
290  static Teuchos::RCP<const Teuchos::ParameterList> valid_params;
291 
292  if( is_null(valid_params) ){
293  Teuchos::RCP<Teuchos::ParameterList> pl = Teuchos::parameterList();
294 
295  pl->set("Reorder", true, "Whether GIDs contiguous");
296 
297  valid_params = pl;
298  }
299 
300  return valid_params;
301 }
302 
303 template <class Matrix, class Vector>
304 bool
306  return (this->root_ && (this->matrixA_->getComm()->getSize() == 1));
307 }
308 
309 template <class Matrix, class Vector>
310 bool
312 {
313  if(current_phase == SOLVE) {
314  return(false);
315  }
316 
317  if(!do_optimization()) { // we're only doing serial right now for cuSolver
318  TEUCHOS_TEST_FOR_EXCEPTION( true, std::runtime_error,
319  "cuSolver is only implemented for serial.");
320  }
321 
322  return true;
323 }
324 
325 template<class Matrix, class Vector>
326 const char* cuSOLVER<Matrix,Vector>::name = "cuSOLVER";
327 
328 } // end namespace Amesos2
329 
330 #endif // AMESOS2_CUSOLVER_DEF_HPP
Amesos2::SolverCore: A templated interface for interaction with third-party direct sparse solvers...
Definition: Amesos2_SolverCore_decl.hpp:105
EPhase
Used to indicate a phase in the direct solution.
Definition: Amesos2_TypeDecl.hpp:65
void setParameters_impl(const Teuchos::RCP< Teuchos::ParameterList > &parameterList)
Definition: Amesos2_cuSOLVER_def.hpp:271
bool matrixShapeOK_impl() const
Determines whether the shape of the matrix is OK for this solver.
Definition: Amesos2_cuSOLVER_def.hpp:264
cuSOLVER(Teuchos::RCP< const Matrix > A, Teuchos::RCP< Vector > X, Teuchos::RCP< const Vector > B)
Initialize from Teuchos::RCP.
Definition: Amesos2_cuSOLVER_def.hpp:57
Teuchos::RCP< const Teuchos::ParameterList > getValidParameters_impl() const
Definition: Amesos2_cuSOLVER_def.hpp:288
Amesos2 interface to cuSOLVER.
Definition: Amesos2_cuSOLVER_decl.hpp:59
int symbolicFactorization_impl()
Perform symbolic factorization of the matrix using cuSOLVER.
Definition: Amesos2_cuSOLVER_def.hpp:108
bool loadA_impl(EPhase current_phase)
Reads matrix data into internal structures.
Definition: Amesos2_cuSOLVER_def.hpp:311
bool do_optimization() const
can we optimize size_type and ordinal_type for straight pass through
Definition: Amesos2_cuSOLVER_def.hpp:305
int numericFactorization_impl()
cuSOLVER specific numeric factorization
Definition: Amesos2_cuSOLVER_def.hpp:134
int preOrdering_impl()
Performs pre-ordering on the matrix to increase efficiency.
Definition: Amesos2_cuSOLVER_def.hpp:86
int solve_impl(const Teuchos::Ptr< MultiVecAdapter< Vector > > X, const Teuchos::Ptr< const MultiVecAdapter< Vector > > B) const
cuSOLVER specific solve.
Definition: Amesos2_cuSOLVER_def.hpp:185
A templated MultiVector class adapter for Amesos2.
Definition: Amesos2_MultiVecAdapter_decl.hpp:176
~cuSOLVER()
Destructor.
Definition: Amesos2_cuSOLVER_def.hpp:77