suanPan
Loading...
Searching...
No Matches
BandMatCUDA.hpp
Go to the documentation of this file.
1/*******************************************************************************
2 * Copyright (C) 2017-2025 Theodore Chang
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 ******************************************************************************/
29// ReSharper disable CppCStyleCast
30#ifndef BANDMATCUDA_HPP
31#define BANDMATCUDA_HPP
32
33#include "../csr_form.hpp"
34#include "BandMat.hpp"
35
36#include <cusolverSp.h>
37#include <cusparse.h>
38
39template<sp_d T> class BandMatCUDA final : public BandMat<T> {
40 cusolverSpHandle_t handle = nullptr;
41 cudaStream_t stream = nullptr;
42 cusparseMatDescr_t descr = nullptr;
43
44 void* d_val_idx = nullptr;
45 void* d_col_idx = nullptr;
46 void* d_row_ptr = nullptr;
47
48 triplet_form<float, int> s_mat{static_cast<int>(this->n_rows), static_cast<int>(this->n_cols), static_cast<int>(this->n_elem)};
49
50 void acquire() {
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));
58 }
59
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);
65 }
66
67 void device_alloc(csr_form<float, int>&& csr_mat) {
68 const size_t n_val = sizeof(float) * csr_mat.n_elem;
69 const size_t n_col = sizeof(int) * csr_mat.n_elem;
70
71 cudaMalloc(&d_val_idx, n_val);
72 cudaMalloc(&d_col_idx, n_col);
73
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);
77 }
78
79 void device_dealloc() const {
80 if(d_val_idx) cudaFree(d_val_idx);
81 if(d_col_idx) cudaFree(d_col_idx);
82 }
83
84protected:
86
87 int direct_solve(Mat<T>&, Mat<T>&&) override;
88
89public:
90 BandMatCUDA(const uword in_size, const uword in_l, const uword in_u)
91 : BandMat<T>(in_size, in_l, in_u) { acquire(); }
92
94 : BandMat<T>(other) { acquire(); }
95
96 BandMatCUDA(BandMatCUDA&&) noexcept = delete;
97 BandMatCUDA& operator=(const BandMatCUDA&) = delete;
98 BandMatCUDA& operator=(BandMatCUDA&&) noexcept = delete;
99
100 ~BandMatCUDA() override {
101 release();
102 device_dealloc();
103 }
104
105 unique_ptr<MetaMat<T>> make_copy() override { return std::make_unique<BandMatCUDA>(*this); }
106};
107
108template<sp_d T> int BandMatCUDA<T>::direct_solve(Mat<T>& X, Mat<T>&& B) {
109 suanpan_assert([&] { if(this->n_rows != this->n_cols) throw invalid_argument("requires a square matrix"); });
110
111 if(!this->factored) {
112 this->factored = true;
113
114 device_dealloc();
115
116 s_mat.zeros();
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));
118
119 device_alloc(csr_form<float, int>(s_mat));
120 }
121
122 const size_t n_rhs = sizeof(float) * B.n_elem;
123
124 void* d_b = nullptr;
125 void* d_x = nullptr;
126
127 cudaMalloc(&d_b, n_rhs);
128 cudaMalloc(&d_x, n_rhs);
129
130 auto INFO = this->mixed_trs(X, std::move(B), [&](fmat& residual) {
131 cudaMemcpyAsync(d_b, residual.memptr(), n_rhs, cudaMemcpyHostToDevice, stream);
132
133 int singularity;
134
135 auto code = 0;
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);
137
138 cudaMemcpyAsync(residual.memptr(), d_x, n_rhs, cudaMemcpyDeviceToHost, stream);
139
140 cudaDeviceSynchronize();
141
142 return code;
143 });
144
145 if(0 != INFO)
146 suanpan_error("Error code {} received, the matrix is probably singular.\n", INFO);
147
148 return INFO;
149}
150
151#endif
152
A BandMatCUDA class that holds matrices.
Definition BandMatCUDA.hpp:39
unique_ptr< MetaMat< T > > make_copy() override
Definition BandMatCUDA.hpp:105
BandMatCUDA(const BandMatCUDA &other)
Definition BandMatCUDA.hpp:93
BandMatCUDA(BandMatCUDA &&) noexcept=delete
BandMatCUDA(const uword in_size, const uword in_l, const uword in_u)
Definition BandMatCUDA.hpp:90
A BandMat class that holds matrices.
Definition BandMat.hpp:35
const uword n_cols
Definition MetaMat.hpp:117
const uword n_rows
Definition MetaMat.hpp:116
const uword n_elem
Definition MetaMat.hpp:118
Definition csr_form.hpp:25
Definition triplet_form.hpp:62
int direct_solve(Mat< T > &, Mat< T > &&) override
Definition BandMatCUDA.hpp:108
void suanpan_assert(const std::function< void()> &F)
Definition suanPan.h:360
#define suanpan_error(...)
Definition suanPan.h:373