I am trying to convert an Eigen Sparse Matrix of size NxN to CuSparse matrix so that I can use CUDA to solver the matrix Ax=B. Came across this thread which is pretty old (Convert Eigen::SparseMatrix to cuSparse and vice versa). I am not sure what is the size of *val in this example and what it represents. Would appreciate any help. I am new to CUDA.
In Eigen's sparse matrix representation:
A.valuePtr()
/ *val
points to the non-zero values (length = A.nonZeros()
).
A.innerIndexPtr()
contains the column indices (if row-major) or row indices (if column-major) corresponding to each non-zero value (length = A.nonZeros()
).
A.outerIndexPtr()
contains offsets marking the start of each row (in row-major CSR) or column (in column-major CSC) in the above arrays (length = N + 1
).
First, make sure your matrix is compressed:
A.makeCompressed();
If you want CSR format explicitly (CuSparse commonly uses CSR), either declare Eigen's matrix as row-major from the beginning:
Eigen::SparseMatrix<float, Eigen::RowMajor> A(N, N);
or transpose before extracting pointers (do not transpose after):
Eigen::SparseMatrix<float, Eigen::RowMajor> A_CSR = A.transpose(); A_CSR.makeCompressed();
Then extract data pointers:
int N = A_CSR.rows();
int nnz = A_CSR.nonZeros();
float* h_val = A_CSR.valuePtr();
int* h_col = A_CSR.innerIndexPtr();
int* h_row = A_CSR.outerIndexPtr();
Allocate GPU memory and copy data:
float* d_val; int* d_col; int* d_row;
cudaMalloc(&d_val, nnz * sizeof(float));
cudaMalloc(&d_col, nnz * sizeof(int));
cudaMalloc(&d_row, (N + 1) * sizeof(int));
cudaMemcpy(d_val, h_val, nnz * sizeof(float), cudaMemcpyHostToDevice);
cudaMemcpy(d_col, h_col, nnz * sizeof(int), cudaMemcpyHostToDevice);
cudaMemcpy(d_row, h_row, (N + 1) * sizeof(int), cudaMemcpyHostToDevice);
Finally, use CuSparse functions (for example, y = A*x
):
cusparseScsrmv(handle,
CUSPARSE_OPERATION_NON_TRANSPOSE,
N, N, nnz,
&alpha,
descr, d_val, d_row, d_col,
d_x, &beta, d_y);
You can use Eigen's valuePtr/innerIndexPtr/outerIndexPtr
this way to copy them to the GPU and let CuSparse handle the rest.