将eigen :: sparsematrix转换为cusparse,反之亦然

Convert Eigen::SparseMatrix to cuSparse and vice versa

本文关键字:cusparse 反之亦然 转换 eigen sparsematrix      更新时间:2023-10-16

我很难弄清楚如何将eigen :: sparsematrix转换为cusparse,因为在线文档和示例很少。对于密集的矩阵,从特征到Cuda转换为Cublas,相当直截了当

Eigen::MatrixXd A = Eigen::MatrixXd::Identity(3,3);
double *d_A;
cudaMalloc(reinterpret_cast<void **>(&d_A), 3 * 3 * sizeof(double));
cudaMemcpy(d_A, A.data(), sizeof(double) * 3 * 3, cudaMemcpyHostToDevice);
// do cublas operations on d_A

如何处理稀疏矩阵?

std::vector<Eigen::Triplet<double>> trip;
trip.emplace_back(0, 0, 1);
trip.emplace_back(1, 1, 1);
trip.emplace_back(2, 2, 1);
Eigen::SparseMatrix<double> A(3, 3);
A.setFromTriplets(trip.begin(), trip.end());
double *d_A;
// cudaMalloc?
// cudaMemcpy? some conversion?
// do cusparse operations

以防万一人们感兴趣,我想知道。棘手的部分是特征的稀疏矩阵是以CSC格式,而Cusparse的格式为CSR格式。幸运的是,可以通过简单地将CSC转换为CSR来完成转换。

void EigenSparseToCuSparseTranspose(
    const Eigen::SparseMatrix<double> &mat, int *row, int *col, double *val)
{
  const int num_non0  = mat.nonZeros();
  const int num_outer = mat.cols() + 1;
  cudaMemcpy(row,
             mat.outerIndexPtr(),
             sizeof(int) * num_outer,
             cudaMemcpyHostToDevice);
  cudaMemcpy(
      col, mat.innerIndexPtr(), sizeof(int) * num_non0, cudaMemcpyHostToDevice);
  cudaMemcpy(
      val, mat.valuePtr(), sizeof(double) * num_non0, cudaMemcpyHostToDevice);
}
void CuSparseTransposeToEigenSparse(
    const int *row,
    const int *col,
    const double *val,
    const int num_non0,
    const int mat_row,
    const int mat_col,
    Eigen::SparseMatrix<double> &mat)
{
  std::vector<int> outer(mat_col + 1);
  std::vector<int> inner(num_non0);
  std::vector<double> value(num_non0);
  cudaMemcpy(
      outer.data(), row, sizeof(int) * (mat_col + 1), cudaMemcpyDeviceToHost);
  cudaMemcpy(inner.data(), col, sizeof(int) * num_non0, cudaMemcpyDeviceToHost);
  cudaMemcpy(
      value.data(), val, sizeof(double) * num_non0, cudaMemcpyDeviceToHost);
  Eigen::Map<Eigen::SparseMatrix<double>> mat_map(
      mat_row, mat_col, num_non0, outer.data(), inner.data(), value.data());
  mat = mat_map.eval();
}