40 cusolverSpHandle_t handle =
nullptr;
41 cudaStream_t stream =
nullptr;
42 cusparseMatDescr_t descr =
nullptr;
44 void* d_val_idx =
nullptr;
45 void* d_col_idx =
nullptr;
46 void* d_row_ptr =
nullptr;
51 cusolverSpCreate(&handle);
52 cudaStreamCreate(&stream);
53 cusolverSpSetStream(handle, stream);
54 cusparseCreateMatDescr(&descr);
55 cusparseSetMatType(descr, CUSPARSE_MATRIX_TYPE_GENERAL);
56 cusparseSetMatIndexBase(descr, CUSPARSE_INDEX_BASE_ZERO);
57 cudaMalloc(&d_row_ptr,
sizeof(
int) * (this->
n_rows + 1));
60 void release()
const {
61 if(handle) cusolverSpDestroy(handle);
62 if(stream) cudaStreamDestroy(stream);
63 if(descr) cusparseDestroyMatDescr(descr);
64 if(d_row_ptr) cudaFree(d_row_ptr);
68 const size_t n_val =
sizeof(float) * csr_mat.n_elem;
69 const size_t n_col =
sizeof(int) * csr_mat.n_elem;
71 cudaMalloc(&d_val_idx, n_val);
72 cudaMalloc(&d_col_idx, n_col);
74 cudaMemcpyAsync(d_val_idx, csr_mat.val_mem(), n_val, cudaMemcpyHostToDevice, stream);
75 cudaMemcpyAsync(d_col_idx, csr_mat.col_mem(), n_col, cudaMemcpyHostToDevice, stream);
76 cudaMemcpyAsync(d_row_ptr, csr_mat.row_mem(),
sizeof(
int) * (csr_mat.n_rows + 1llu), cudaMemcpyHostToDevice, stream);
79 void device_dealloc()
const {
80 if(d_val_idx) cudaFree(d_val_idx);
81 if(d_col_idx) cudaFree(d_col_idx);
90 BandMatCUDA(
const uword in_size,
const uword in_l,
const uword in_u)
91 :
BandMat<
T>(in_size, in_l, in_u) { acquire(); }
105 unique_ptr<MetaMat<T>>
make_copy()
override {
return std::make_unique<BandMatCUDA>(*
this); }
109 suanpan_assert([&] {
if(this->n_rows != this->n_cols)
throw invalid_argument(
"requires a square matrix"); });
111 if(!this->factored) {
112 this->factored =
true;
117 for(
auto I = 0; I < static_cast<int>(this->n_rows); ++I)
for(
auto J = std::max(0, I -
static_cast<int>(this->u_band)); J <= std::min(static_cast<int>(this->n_rows) - 1, I +
static_cast<int>(this->l_band)); ++J) s_mat.at(J, I) =
static_cast<float>(this->at(J, I));
122 const size_t n_rhs =
sizeof(float) * B.n_elem;
127 cudaMalloc(&d_b, n_rhs);
128 cudaMalloc(&d_x, n_rhs);
130 auto INFO = this->mixed_trs(X, std::move(B), [&](fmat& residual) {
131 cudaMemcpyAsync(d_b, residual.memptr(), n_rhs, cudaMemcpyHostToDevice, stream);
136 for(
auto I = 0llu; I < residual.n_elem; I += residual.n_rows) code += cusolverSpScsrlsvqr(handle,
static_cast<int>(this->n_rows),
static_cast<int>(this->s_mat.n_elem), descr, (
float*)d_val_idx, (
int*)d_row_ptr, (
int*)d_col_idx, (
float*)d_b + I,
static_cast<float>(this->setting.tolerance), 3, (
float*)d_x + I, &singularity);
138 cudaMemcpyAsync(residual.memptr(), d_x, n_rhs, cudaMemcpyDeviceToHost, stream);
140 cudaDeviceSynchronize();
146 suanpan_error(
"Error code {} received, the matrix is probably singular.\n", INFO);