61 Teuchos::RCP<const Matrix> A,
62 Teuchos::RCP<Vector> X,
63 Teuchos::RCP<const Vector> B )
66 auto status = cusolverDnCreate(&data_.dn_handle);
67 TEUCHOS_TEST_FOR_EXCEPTION( status != CUSOLVER_STATUS_SUCCESS,
68 std::runtime_error,
"cusolverDnCreate failed");
69 status = cusolverSpCreate(&data_.sp_handle);
70 TEUCHOS_TEST_FOR_EXCEPTION( status != CUSOLVER_STATUS_SUCCESS,
71 std::runtime_error,
"cusolverSpCreate failed");
72 status = cusolverSpCreateCsrcholInfo(&data_.chol_info);
73 TEUCHOS_TEST_FOR_EXCEPTION( status != CUSOLVER_STATUS_SUCCESS,
74 std::runtime_error,
"cusolverSpCreateCsrcholInfo failed");
75 auto sparse_status = cusparseCreateMatDescr(&data_.desc);
76 TEUCHOS_TEST_FOR_EXCEPTION( sparse_status != CUSPARSE_STATUS_SUCCESS,
77 std::runtime_error,
"cusparseCreateMatDescr failed");
78 auto blas_status = cublasCreate(&data_.blas_handle);
79 TEUCHOS_TEST_FOR_EXCEPTION( blas_status != CUBLAS_STATUS_SUCCESS,
80 std::runtime_error,
"cublasCreate failed");
83 cublasSetStream(data_.blas_handle,
84 Kokkos::DefaultExecutionSpace().cuda_stream());
125#ifdef HAVE_AMESOS2_TIMERS
126 Teuchos::TimeMonitor symFactTimer(this->timers_.symFactTime_);
131 const int n = this->globalNumRows_;
133 if(n > data_.small_matrix_threshold) {
134 if(device_row_ptr_view_.extent(0) == 0) {
135 this->matrixA_->returnRowPtr_kokkos_view(device_row_ptr_view_);
136 this->matrixA_->returnColInd_kokkos_view(device_cols_view_);
138 const int nnz = device_cols_view_.size();
139 const int * colIdx = device_cols_view_.data();
140 const int * rowPtr = device_row_ptr_view_.data();
141 auto status = cusolverSpXcsrcholAnalysis(
142 data_.sp_handle, n, nnz, data_.desc, rowPtr, colIdx, data_.chol_info);
143 err = (status != CUSOLVER_STATUS_SUCCESS) ? 1 : 0;
146 if((
int)device_matrix_.extent(0) != n) {
147 device_matrix_ = device_value_type_matrix(
148 Kokkos::ViewAllocateWithoutInitializing(
"cusolver_dense"), n, n);
149 device_ipiv_ = Kokkos::View<int*, device_type>(
150 Kokkos::ViewAllocateWithoutInitializing(
"cusolver_ipiv"), n);
151 device_info_ = Kokkos::View<int, device_type>(
"cusolver_info");
153 if((
int)device_inverse_.extent(0) != n) {
154 device_inverse_ = device_value_type_matrix(
155 Kokkos::ViewAllocateWithoutInitializing(
"cusolver_inverse"), n, n);
160 auto status = function_map::bufferInfo(
161 data_.dn_handle, n, device_matrix_.data(), n, &lwork);
162 if(status == CUSOLVER_STATUS_SUCCESS) {
163 if((
size_t)lwork > buffer_.extent(0)) {
164 buffer_ = device_value_type_array(
165 Kokkos::ViewAllocateWithoutInitializing(
"cusolver_buf"), lwork);
168 err = (status != CUSOLVER_STATUS_SUCCESS) ? 1 : 0;
172 Teuchos::broadcast(*(this->getComm()), 0, &err);
173 TEUCHOS_TEST_FOR_EXCEPTION(err != 0,
174 std::runtime_error,
"Amesos2 cuSolver symbolic failed.");
183#ifdef HAVE_AMESOS2_TIMERS
184 Teuchos::TimeMonitor numFactTimer(this->timers_.numFactTime_);
188 if(do_optimization()) {
189 const int n = this->globalNumRows_;
191 if(n > data_.small_matrix_threshold) {
192 this->matrixA_->returnValues_kokkos_view(device_nzvals_view_);
198 device_size_type_array orig_device_row_ptr_view;
199 device_ordinal_type_array orig_device_cols_view;
200 this->matrixA_->returnRowPtr_kokkos_view(orig_device_row_ptr_view);
201 this->matrixA_->returnColInd_kokkos_view(orig_device_cols_view);
202 Amesos2::Util::reorder_values(
203 device_nzvals_view_, orig_device_row_ptr_view, device_row_ptr_view_,
204 orig_device_cols_view, device_perm_, device_peri_, sorted_nnz);
207 const int nnz = device_cols_view_.size();
208 const cusolver_type * values = device_nzvals_view_.data();
209 const int * colIdx = device_cols_view_.data();
210 const int * rowPtr = device_row_ptr_view_.data();
212 size_t internalDataInBytes, workspaceInBytes;
213 auto status = function_map::sparseBufferInfo(
214 data_.sp_handle, n, nnz, data_.desc,
215 values, rowPtr, colIdx, data_.chol_info,
216 &internalDataInBytes, &workspaceInBytes);
218 if(status == CUSOLVER_STATUS_SUCCESS) {
219 const size_t buffer_size = workspaceInBytes /
sizeof(cusolver_type);
220 if(buffer_size > buffer_.extent(0)) {
221 buffer_ = device_value_type_array(
222 Kokkos::ViewAllocateWithoutInitializing(
"cusolver_buf"), buffer_size);
224 status = function_map::sparseNumeric(
225 data_.sp_handle, n, nnz, data_.desc,
226 values, rowPtr, colIdx, data_.chol_info, buffer_.data());
228 err = (status != CUSOLVER_STATUS_SUCCESS) ? 1 : 0;
229 Teuchos::broadcast(*(this->getComm()), 0, &err);
230 TEUCHOS_TEST_FOR_EXCEPTION(err != 0,
231 std::runtime_error,
"Amesos2 cuSolver numeric failed.");
237 device_value_type_array nzvals;
238 device_size_type_array row_ptr;
239 device_ordinal_type_array col_ind;
240 this->matrixA_->returnValues_kokkos_view(nzvals);
241 this->matrixA_->returnRowPtr_kokkos_view(row_ptr);
242 this->matrixA_->returnColInd_kokkos_view(col_ind);
245 Kokkos::deep_copy(device_matrix_,
246 Teuchos::ScalarTraits<cusolver_type>::zero());
247 Impl::CsrToDenseFunctor<device_value_type_matrix,
248 device_size_type_array,
249 device_ordinal_type_array,
250 device_value_type_array>
251 scatter(device_matrix_, row_ptr, col_ind, nzvals);
252 Kokkos::parallel_for(
"Amesos2_cuSOLVER_csr_to_dense",
253 Kokkos::RangePolicy<typename device_type::execution_space>(0, n),
257 auto status = function_map::numeric(
258 data_.dn_handle, n, device_matrix_.data(), n,
259 buffer_.data(), device_ipiv_.data(), device_info_.data());
261 if(status == CUSOLVER_STATUS_SUCCESS) {
263 Impl::SetIdentityFunctor<device_value_type_matrix> set_id(device_inverse_);
264 Kokkos::parallel_for(
"Amesos2_cuSOLVER_set_identity",
265 Kokkos::RangePolicy<typename device_type::execution_space>(0, n),
268 status = function_map::solveLU(
269 data_.dn_handle, CUBLAS_OP_N, n, n,
270 device_matrix_.data(), n, device_ipiv_.data(),
271 device_inverse_.data(), n, device_info_.data());
274 if(status == CUSOLVER_STATUS_SUCCESS) {
275 auto host_info = Kokkos::create_mirror_view_and_copy(
276 Kokkos::HostSpace(), device_info_);
277 err = (host_info() != 0) ? 1 : 0;
283 Teuchos::broadcast(*(this->getComm()), 0, &err);
284 TEUCHOS_TEST_FOR_EXCEPTION(err != 0,
285 std::runtime_error,
"Amesos2 cuSolver numeric failed.");
297 const int n = this->globalNumRows_;
299 if(n > data_.small_matrix_threshold) {
300 TEUCHOS_TEST_FOR_EXCEPTION(this->control_.useTranspose_,
302 "Amesos2 cuSolver sparse Cholesky path does not support transpose solves.");
304 const global_size_type ld_rhs = this->root_ ? X->getGlobalLength() : 0;
305 const ordinal_type nrhs = X->getGlobalNumVectors();
309#ifdef HAVE_AMESOS2_TIMERS
310 Teuchos::TimeMonitor mvConvTimer(this->timers_.vecConvTime_);
313 const bool initialize_data =
true;
314 const bool do_not_initialize_data =
false;
315 Util::get_1d_copy_helper_kokkos_view<MultiVecAdapter<Vector>,
316 device_solve_array_t>::do_get(initialize_data, B, this->bValues_,
317 Teuchos::as<size_t>(ld_rhs),
ROOTED, this->rowIndexBase_);
319 bAssignedX = Util::get_1d_copy_helper_kokkos_view<MultiVecAdapter<Vector>,
320 device_solve_array_t>::do_get(do_not_initialize_data, X, this->xValues_,
321 Teuchos::as<size_t>(ld_rhs),
ROOTED, this->rowIndexBase_);
325#ifdef HAVE_AMESOS2_TIMERS
326 Teuchos::TimeMonitor solveTimer(this->timers_.solveTime_);
330 Amesos2::Util::apply_reorder_permutation(
331 this->bValues_, this->permute_result_, this->device_perm_);
334 this->permute_result_ = this->bValues_;
337 for(ordinal_type rhs = 0; rhs < nrhs; ++rhs) {
338 const cusolver_type * b = this->permute_result_.data() + rhs * n;
339 cusolver_type * x = this->xValues_.data() + rhs * n;
340 auto status = function_map::sparseSolve(
341 data_.sp_handle, n, b, x, data_.chol_info, buffer_.data());
342 err = (status != CUSOLVER_STATUS_SUCCESS) ? 1 : 0;
348 if(data_.bReorder && err == 0) {
349 Amesos2::Util::apply_reorder_permutation(
350 this->xValues_, this->permute_result_, this->device_peri_);
351 Kokkos::deep_copy(this->xValues_, this->permute_result_);
356#ifdef HAVE_AMESOS2_TIMERS
357 Teuchos::TimeMonitor redistTimer(this->timers_.vecRedistTime_);
360 Util::template put_1d_data_helper_kokkos_view<
362 Teuchos::as<size_t>(ld_rhs),
ROOTED, this->rowIndexBase_);
365 Teuchos::broadcast(*(this->getComm()), 0, &err);
366 TEUCHOS_TEST_FOR_EXCEPTION(err != 0,
367 std::runtime_error,
"Amesos2 cuSolver solve failed.");
372 const global_size_type ld_rhs = this->root_ ? X->getGlobalLength() : 0;
375#ifdef HAVE_AMESOS2_TIMERS
376 Teuchos::TimeMonitor mvConvTimer(this->timers_.vecConvTime_);
382 const bool initialize_data =
true;
383 const bool do_not_initialize_data =
false;
384 Util::get_1d_copy_helper_kokkos_view<MultiVecAdapter<Vector>,
385 device_solve_array_t>::do_get(initialize_data, B, this->bValues_,
386 Teuchos::as<size_t>(ld_rhs),
ROOTED, this->rowIndexBase_);
387 bAssignedX = Util::get_1d_copy_helper_kokkos_view<MultiVecAdapter<Vector>,
388 device_solve_array_t>::do_get(do_not_initialize_data, X, this->xValues_,
389 Teuchos::as<size_t>(ld_rhs),
ROOTED, this->rowIndexBase_);
393#ifdef HAVE_AMESOS2_TIMERS
394 Teuchos::TimeMonitor solveTimer(this->timers_.solveTime_);
396 const int nrhs =
static_cast<int>(X->getGlobalNumVectors());
397 const int ldb = std::max(n,
static_cast<int>(this->bValues_.stride(1)));
398 const int ldx = std::max(n,
static_cast<int>(this->xValues_.stride(1)));
400 const cublasOperation_t trans =
401 this->control_.useTranspose_ ? CUBLAS_OP_C : CUBLAS_OP_N;
403 auto blas_status = function_map::solve(
404 data_.blas_handle, trans, n, nrhs,
405 device_inverse_.data(), n,
406 this->bValues_.data(), ldb, this->xValues_.data(), ldx);
408 err = (blas_status != CUBLAS_STATUS_SUCCESS) ? 1 : 0;
411 Teuchos::broadcast(*(this->getComm()), 0, &err);
412 TEUCHOS_TEST_FOR_EXCEPTION(err != 0,
413 std::runtime_error,
"Amesos2 cuSolver solve failed.");
416#ifdef HAVE_AMESOS2_TIMERS
417 Teuchos::TimeMonitor redistTimer(this->timers_.vecRedistTime_);
420 Util::template put_1d_data_helper_kokkos_view<
422 X, this->xValues_, Teuchos::as<size_t>(ld_rhs),
ROOTED,
423 this->rowIndexBase_);