我是Eigen和CUDA的初学者。
我正在尝试使用Eigen Sparse Matrix在CUDA中工作,特别是我想将指向不等于0的值的指针传递给内核。
该代码有效,但输出不正确。应该是这样的

0.3 0.3 0.3
0.3 0.3 0.3
0   0   0
但我得到类似的东西:
0.3 0.3 0.3 0 0 4.94066e-324 0
0.3 0.3 1.63042e-322
0 0 0
我的第二个问题是:如何仅将非0的值复制到内核中?
这是代码:
 #include <chrono>
#include <iomanip>
#include <iostream>
#include <random>
#include <Eigen/SparseCore>
#include <Eigen/Core>

const int BLOCK_DIM = 8;


__global__ void cu_fun(double *input, double *out, int N){
    int idx = blockIdx.x * blockDim.x + threadIdx.x;
    if(idx < N){
        out[idx] = input[idx]/10;
    }
}

int main(){

int n = 3;
int nrow = n;
int ncol = n;
Eigen::SparseMatrix <double> spMat(n,n);
Eigen::SparseMatrix <double> out(n,n);


for(int i = 0; i < 2; i++){
    for(int j = 0; j<3; j++){
        spMat.insert(i,j) = 3;
    }
}

const int non0 = spMat.nonZeros();
std::vector <double> value(non0);
double *dev_in = new double[non0];
double *dev_ret = new double[non0];


cudaMalloc((void **)&dev_in, sizeof(double)*non0);
cudaMalloc((void **)&dev_ret, sizeof(double)*non0);

cudaMemcpy(dev_in, spMat.valuePtr(), sizeof(double) * non0, cudaMemcpyHostToDevice);


cu_fun<<< 8,1>>>(dev_in, dev_ret, non0);


cudaMemcpy(value.data(), dev_ret, sizeof(double) * non0, cudaMemcpyDeviceToHost);


Eigen::Map<Eigen::SparseMatrix<double>> mat_map(nrow, ncol, non0, spMat.outerIndexPtr(), spMat.innerIndexPtr(), value.data());

out = mat_map.eval();

std::cout << spMat
          << "\n"
<< out;
}

最佳答案

从本征documentation报价为Eigen::SparseMatrix
您的代码假定spMat中的所有非零条目都在spMat.valuePtr()spMat.valuePtr()+spMat.nonZeros()的范围内。仅当矩阵被压缩时才会如此。您的矩阵未压缩。如果在赋值后添加对spMat.makeCompressed()的调用,则应该发现该代码可以正常工作。修改数组构造并将其复制为非零值:

Eigen::SparseMatrix <double> spMat(n,n);
for(int i = 0; i < 2; i++){
    for(int j = 0; j<3; j++){
        spMat.insert(i,j) = 3;
    }
}

spMat.makeCompressed();
const int non0 = spMat.nonZeros();
std::vector <double> value(non0);
double *dev_in; cudaMalloc((void **)&dev_in, sizeof(double)*non0);
double *dev_ret; cudaMalloc((void **)&dev_ret, sizeof(double)*non0);
cudaMemcpy(dev_in, spMat.valuePtr(), sizeof(double) * non0, cudaMemcpyHostToDevice);
[请注意,您包含并分配给newdev_indev_out调用是多余的,仅用于泄漏内存]
给我这个:
$  nvcc -arch=sm_53 -std=c++11 -o eigennono -I $EIGENPATH eigennono.cu
$ ./eigennono
Nonzero entries:
(3,0) (3,1) (3,0) (3,1) (3,0) (3,1)

Outer pointers:
0 2 4  $

3 3 3
3 3 3
0 0 0

Nonzero entries:
(0.3,0) (0.3,1) (0.3,0) (0.3,1) (0.3,0) (0.3,1)

Outer pointers:
0 2 4  $

0.3 0.3 0.3
0.3 0.3 0.3
0 0 0

关于c++ - 如何在GPU内核中使用Eigen稀疏矩阵,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/63174892/

10-11 16:00