C++ 如何在GPU内核中使用特征稀疏矩阵

C++ 如何在GPU内核中使用特征稀疏矩阵,c++,cuda,eigen,C++,Cuda,Eigen,我是伊根和库达的初学者。 我试图在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 <

我是伊根和库达的初学者。 我试图在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;
}
#包括
#包括
#包括
#包括
#包括
#包括
常数int BLOCK_DIM=8;
__全局无效cu\U fun(双*输入,双*输出,整数N){
int idx=blockIdx.x*blockDim.x+threadIdx.x;
if(idxEigen::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);

这显然不是您正在运行的代码,您发布的内容甚至无法编译。如果您需要帮助,请发布一个有用的重新编译案例。我上传了工作代码,并重新编写了问题。感谢您的帮助!谢谢!使用makeCompressed()一切正常!我还有另一个疑问,代码正常,但当我尝试使用大于250x250的稀疏矩阵时,输出为零矩阵!这是因为GPU的内存限制吗?你知道解决方案吗?我使用的块数为非0/BLOCK_DIM,BLOCK_DIM为64。谢谢!@talonmies
$  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