C++ 如何在GPU内核中使用特征稀疏矩阵
我是伊根和库达的初学者。 我试图在CUDA中使用特征稀疏矩阵,特别是我想将指向不等于0的值的指针传递给内核。 代码正常,但输出不正确。应该是这样的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 <
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