38 cusolverDnHandle_t handle =
nullptr;
39 cudaStream_t stream =
nullptr;
44 void* buffer =
nullptr;
47 cusolverDnCreate(&handle);
48 cudaStreamCreate(&stream);
49 cusolverDnSetStream(handle, stream);
51 cudaMalloc(&info,
sizeof(
int));
52 cudaMemset(info, 0,
sizeof(
int));
53 cudaMalloc(&ipiv,
sizeof(
int) * this->
n_rows);
56 if constexpr(std::is_same_v<T, float>) {
57 cudaMalloc(&d_A,
sizeof(
float) * this->
n_elem);
58 cusolverDnSgetrf_bufferSize(handle,
static_cast<int>(this->n_rows),
static_cast<int>(this->
n_cols), (
float*)d_A,
static_cast<int>(this->n_elem), &bufferSize);
59 cudaMalloc(&buffer,
sizeof(
float) * bufferSize);
62 cudaMalloc(&d_A,
sizeof(
float) * this->
n_elem);
63 cusolverDnSgetrf_bufferSize(handle,
static_cast<int>(this->n_rows),
static_cast<int>(this->
n_cols), (
float*)d_A,
static_cast<int>(this->n_elem), &bufferSize);
64 cudaMalloc(&buffer,
sizeof(
float) * bufferSize);
67 cudaMalloc(&d_A,
sizeof(
double) * this->
n_elem);
68 cusolverDnDgetrf_bufferSize(handle,
static_cast<int>(this->n_rows),
static_cast<int>(this->
n_cols), (
double*)d_A,
static_cast<int>(this->n_elem), &bufferSize);
69 cudaMalloc(&buffer,
sizeof(
double) * bufferSize);
73 void release()
const {
74 if(handle) cusolverDnDestroy(handle);
75 if(stream) cudaStreamDestroy(stream);
77 if(info) cudaFree(info);
78 if(d_A) cudaFree(d_A);
79 if(buffer) cudaFree(buffer);
80 if(ipiv) cudaFree(ipiv);
90 :
FullMat<
T>(in_rows, in_cols) { acquire(); }
101 unique_ptr<MetaMat<T>>
make_copy()
override {
return std::make_unique<FullMatCUDA>(*
this); }
105 if constexpr(std::is_same_v<T, float>) {
107 if(!this->factored) {
108 this->factored =
true;
109 cudaMemcpyAsync(d_A, this->memptr(),
sizeof(
float) * this->n_elem, cudaMemcpyHostToDevice, stream);
110 cusolverDnSgetrf(handle,
static_cast<int>(this->n_rows),
static_cast<int>(this->n_cols), (
float*)d_A,
static_cast<int>(this->n_rows), (
float*)buffer, ipiv, info);
113 const size_t byte_size =
sizeof(float) * B.n_elem;
116 cudaMalloc(&d_x, byte_size);
117 cudaMemcpyAsync(d_x, B.memptr(), byte_size, cudaMemcpyHostToDevice, stream);
118 cusolverDnSgetrs(handle, CUBLAS_OP_N,
static_cast<int>(this->n_rows),
static_cast<int>(B.n_cols), (
float*)d_A,
static_cast<int>(this->n_rows), ipiv, (
float*)d_x,
static_cast<int>(this->n_rows), info);
120 X.set_size(arma::size(B));
122 cudaMemcpyAsync(X.memptr(), d_x, byte_size, cudaMemcpyDeviceToHost, stream);
124 cudaDeviceSynchronize();
126 if(d_x) cudaFree(d_x);
130 if(!this->factored) {
131 this->factored =
true;
132 this->s_memory = this->to_float();
133 cudaMemcpyAsync(d_A, this->s_memory.memptr(),
sizeof(
float) * this->s_memory.n_elem, cudaMemcpyHostToDevice, stream);
134 cusolverDnSgetrf(handle,
static_cast<int>(this->n_rows),
static_cast<int>(this->n_cols), (
float*)d_A,
static_cast<int>(this->n_rows), (
float*)buffer, ipiv, info);
137 const size_t byte_size =
sizeof(float) * B.n_elem;
140 cudaMalloc(&d_x, byte_size);
142 X = arma::zeros(B.n_rows, B.n_cols);
144 mat full_residual = B;
146 auto multiplier = norm(full_residual);
148 auto counter = std::uint8_t{0};
149 while(counter++ < this->setting.iterative_refinement) {
150 if(multiplier < this->setting.tolerance)
break;
152 auto residual = conv_to<fmat>::from(full_residual / multiplier);
154 cudaMemcpyAsync(d_x, residual.memptr(), byte_size, cudaMemcpyHostToDevice, stream);
155 cusolverDnSgetrs(handle, CUBLAS_OP_N,
static_cast<int>(this->n_rows),
static_cast<int>(B.n_cols), (
float*)d_A,
static_cast<int>(this->n_rows), ipiv, (
float*)d_x,
static_cast<int>(this->n_rows), info);
156 cudaMemcpyAsync(residual.memptr(), d_x, byte_size, cudaMemcpyDeviceToHost, stream);
158 cudaDeviceSynchronize();
160 const mat incre = multiplier * conv_to<mat>::from(residual);
164 suanpan_debug(
"Mixed precision algorithm multiplier: {:.5E}.\n", multiplier = arma::norm(full_residual -= this->
operator*(incre)));
167 if(d_x) cudaFree(d_x);
171 if(!this->factored) {
172 this->factored =
true;
173 cudaMemcpyAsync(d_A, this->memptr(),
sizeof(
double) * this->n_elem, cudaMemcpyHostToDevice, stream);
174 cusolverDnDgetrf(handle,
static_cast<int>(this->n_rows),
static_cast<int>(this->n_cols), (
double*)d_A,
static_cast<int>(this->n_rows), (
double*)buffer, ipiv, info);
177 const size_t byte_size =
sizeof(double) * B.n_elem;
180 cudaMalloc(&d_x, byte_size);
181 cudaMemcpyAsync(d_x, B.memptr(), byte_size, cudaMemcpyHostToDevice, stream);
182 cusolverDnDgetrs(handle, CUBLAS_OP_N,
static_cast<int>(this->n_rows),
static_cast<int>(B.n_cols), (
double*)d_A,
static_cast<int>(this->n_rows), ipiv, (
double*)d_x,
static_cast<int>(this->n_rows), info);
184 X.set_size(arma::size(B));
186 cudaMemcpyAsync(X.memptr(), d_x, byte_size, cudaMemcpyDeviceToHost, stream);
188 cudaDeviceSynchronize();
190 if(d_x) cudaFree(d_x);