【发布时间】:2018-04-11 17:58:24
【问题描述】:
关于在我的 cuda 函数中调用 JacobiSVD 时出现错误。
这是导致错误的代码部分。
Eigen::JacobiSVD<Eigen::Matrix3d> svd( cov_e, Eigen::ComputeThinU | Eigen::ComputeThinV);
这是错误信息。
CUDA_voxel_building.cu(43):错误:调用 __host__ 来自 __global__ 的函数(“Eigen::JacobiSVD, (int)2> ::JacobiSVD”) 不允许使用函数(“内核”)
我使用下面的命令来编译它。
nvcc -std=c++11 -D_MWAITXINTRIN_H_INCLUDED -D__STRICT_ANSI__ -ptx CUDA_voxel_building.cu
我在 ubuntu 16.04 上使用带有 eigen3 的代码 8.0。 似乎特征值分解等其他函数也给出了相同的错误。
有人知道解决方案吗?我在下面附上了我的代码。
//nvcc -ptx CUDA_voxel_building.cu
#include </usr/include/eigen3/Eigen/Core>
#include </usr/include/eigen3/Eigen/SVD>
/*
#include </usr/include/eigen3/Eigen/Sparse>
#include </usr/include/eigen3/Eigen/Dense>
#include </usr/include/eigen3/Eigen/Eigenvalues>
*/
__global__ void kernel(double *p, double *breaks,double *ind, double *mu, double *cov, double *e,double *v, int *n, char *isgood, int minpts, int maxgpu){
bool debuginfo = false;
int idx = threadIdx.x + blockIdx.x * blockDim.x;
if(debuginfo)printf("Thread %d got pointer\n",idx);
if( idx < maxgpu){
int s_ind = breaks[idx];
int e_ind = breaks[idx+1];
int diff = e_ind-s_ind;
if(diff >minpts){
int cnt = 0;
Eigen::MatrixXd local_p(3,diff) ;
for(int k = s_ind;k<e_ind;k++){
int temp_ind=ind[k];
//Eigen::Matrix<double, 3, diff> local_p;
local_p(1,cnt) = p[temp_ind*3];
local_p(2,cnt) = p[temp_ind*3+1];
local_p(3,cnt) = p[temp_ind*3+2];
cnt++;
}
Eigen::Matrix3d centered = local_p.rowwise() - local_p.colwise().mean();
Eigen::Matrix3d cov_e = (centered.adjoint() * centered) / double(local_p.rows() - 1);
Eigen::JacobiSVD<Eigen::Matrix3d> svd( cov_e, Eigen::ComputeThinU | Eigen::ComputeThinV);
/* Eigen::Matrix3d Cp = svd.matrixU() * svd.singularValues().asDiagonal() * svd.matrixV().transpose();
mu[idx]=p[ind[s_ind]*3];
mu[idx+1]=p[ind[s_ind+1]*3];
mu[idx+2]=p[ind[s_ind+2]*3];
e[idx]=svd.singularValues()(0);
e[idx+1]=svd.singularValues()(1);
e[idx+2]=svd.singularValues()(2);
n[idx] = diff;
isgood[idx] = 1;
for(int x = 0; x < 3; x++)
{
for(int y = 0; y < 3; y++)
{
v[x+ 3*y +idx*9]=svd.matrixV()(x, y);
cov[x+ 3*y +idx*9]=cov_e(x, y);
//if(debuginfo)printf("%f ",R[x+ 3*y +i*9]);
if(debuginfo)printf("%f ",Rm(x, y));
}
}
*/
} else {
mu[idx]=0;
mu[idx+1]=0;
mu[idx+2]=0;
e[idx]=0;
e[idx+1]=0;
e[idx+2]=0;
n[idx] = 0;
isgood[idx] = 0;
for(int x = 0; x < 3; x++)
{
for(int y = 0; y < 3; y++)
{
v[x+ 3*y +idx*9]=0;
cov[x+ 3*y +idx*9]=0;
}
}
}
}
}
【问题讨论】:
-
没有解决办法。您不能只从内核内部调用随机主机代码。除非有专门编写的设备代码库(我强烈怀疑在这种情况下没有)。那么你试图做的事情是不可能的。
-
谢谢,talonmies。我知道我不能从内核内部调用主机代码,但据我所知 cuda 8.0 支持 Eigen。而且我已经在我的一些内核函数中使用了 Eigen。我认为我的问题仅与 JacobiSVD 和 Eigen 中的其他特定功能有关。你还说问题只是因为在内核中调用了host函数吗?
-
Eigen 中的一些简单函数和容器类型已扩展为在 GPU 上工作。 AFAIK,大多数图书馆都没有。至于CUDA 8“支持特征”,这意味着您可以使用nvcc编译主机特征代码而不会炸毁CUDA前端,这曾经是这种情况。
-
@talonmies 这个问题非常具有本征特征,IMO 并不是您链接到的问题的副本。例如,我认为
Eigen::SelfAdjointEigenSolver适用于 cuda(具有固定大小的矩阵)。在这里使用它更有意义,因为cov_e是自伴随的 -
@chtz:好的,现在这是一个开放的特征问题。试试吧。