Cuda 内核启动失败-花费-100%的时间在GPU上运行
内核Cuda 内核启动失败-花费-100%的时间在GPU上运行,cuda,Cuda,内核更新\u umatrix启动失败,分析器显示需要-100%!计算时间 这可能是一个简单的问题,但我已经花了两周的时间来解决这个问题,根据nsight profiler,内核的启动还是以某种方式无法启动,至少U矩阵没有更新并且包含所有零(这是FCM的部分实现) 我的GPU是GeForce 330M,计算能力为1.2 float *U; float *V; float *X; __device__ float *U_d; __device__ float *V_d; __device__ fl
更新\u umatrix
启动失败,分析器显示需要-100%
!计算时间
这可能是一个简单的问题,但我已经花了两周的时间来解决这个问题,根据nsight profiler,内核的启动还是以某种方式无法启动,至少U
矩阵没有更新并且包含所有零(这是FCM的部分实现)
我的GPU是GeForce 330M,计算能力为1.2
float *U;
float *V;
float *X;
__device__ float *U_d;
__device__ float *V_d;
__device__ float *X_d;
__global__ void update_umatrix(float *sqrerror,int C,int N,int S,float m)
{
int i,j,k;
int example_is_centroid;
float summation, D_ki, D_kj;
float newU;
__shared__ float tmp_sqrerror[DIM];
/* For each example in the dataset */
k = threadIdx.x + blockIdx.x*blockDim.x;
int local_offset = threadIdx.x;
tmp_sqrerror[local_offset]=0;
/* Special case: If Example is equal to a Cluster Centroid,
then U=1.0 for that cluster and 0 for all others */
if ( (example_is_centroid=is_example_centroid(k,S,C)) != -1 ) {
for(int i=0; i<C; i++)
{
if ( i == example_is_centroid )
U_d[k*C+i]=1.0;
else
U_d[k*C+i]=0.0;
}
return;
}
/* For each class */
for(int i=0; i< C; i++)
{
summation=0;
/* Calculate summation */
for (j=0; j < C; j++) {
D_ki=distance(X_d, V_d,k*DIM,i*S,S);
D_kj=distance(X_d, V_d,k*DIM,j*S,S);
summation += powf( D_ki / D_kj , (2.0/ (m-1)));
}
/* Weight is 1/sum */
newU=1.0/summation;
/* Add to the squareDifference */
tmp_sqrerror[local_offset] += powf(U_d[k*C+i] - newU, 2);
U_d[k*C+i]=newU;
}
__syncthreads();
int t= blockDim.x/2;
while(t>0)
{
if(k+t < N && threadIdx.x<t)
tmp_sqrerror[local_offset] += tmp_sqrerror[local_offset+t];
t/=2;
__syncthreads();
}
if(threadIdx.x==0)
sqrerror[blockIdx.x] = tmp_sqrerror[0];
}
int init()
{
float m = 2.0;
int C=2;
int S=2;
int N=340*340;
int i,j;
/* Allocate necessary storage */
V=(float *)CALLOC(S*C, sizeof(float));
U=(float *)CALLOC(C*N,sizeof(float));
cudaGetErrorString(cudaMalloc(&U_d,N*C*sizeof(float)));
cudaGetErrorString(cudaMalloc(&V_d,C*S*sizeof(float)));
/* Place random values in V, then update U matrix based on it */
srand48(seed);
for (i=0; i < C; i++) {
for (j=0; j < S; j++) {
V[i*S+j]=drand48() * max_value[j];
}
}
float *dummy;
cudaMalloc(&dummy,N*sizeof(float));
cudaGetErrorString(cudaMemcpyToSymbol(&V_d,V,C*S*sizeof(float),0,cudaMemcpyHostToDevice));
/* Once values are populated in V, update the U Matrix for sane values */
update_umatrix<<<(N+DIM-1)/DIM,DIM>>>(dummy,C,N,S,m);
cudaGetErrorString(cudaGetLastError());
cudaDeviceSynchronize();
cudaGetErrorString(cudaMemcpyFromSymbol(U,&U_d,N*C*sizeof(float),cudaMemcpyDeviceToHost));
fprintf(stdout,"Initialization completed.\n");
return 0;
}
float*U;
浮动*V;
浮动*X;
__设备浮点数*浮点数;
__设备浮动*V\U d;
__设备浮点数*X\u d;
__全局无效更新矩阵(浮点*sqrerror,int C,int N,int S,float m)
{
int i,j,k;
int示例_是_形心;
浮点数总和,D_ki,D_kj;
浮动纽乌;
__共享浮点数tmp sqrerror[DIM];
/*对于数据集中的每个示例*/
k=螺纹IDX.x+块IDX.x*块尺寸.x;
int local_offset=threadIdx.x;
tmp_sqrerror[本地_偏移]=0;
/*特殊情况:如果示例等于簇质心,
然后该集群的U=1.0,其他集群的U=0*/
如果((示例是质心=示例是质心(k,S,C))!=-1){
对于(int i=0;i0)
{
如果(k+t
cudaGetErrorString(cudaMemcpyToSymbol(&V_d,V,C*S*sizeof(float),0,cudaMemcpyHostToDevice));
它会编译,但在运行时会抛出一个错误。因为你似乎用错误检查包装了它,我只能假设你的错误检查被破坏了
传递给cudaMemcpyToSymbol
的符号必须是有效的符号,只能是。它不能是符号的地址、符号加偏移量或类似的内容
我还认为这一行代码是不明智的,尽管我无法向自己证明它不起作用:
cudaGetErrorString(cudaMalloc(&V_d,C*S*sizeof(float)));
如果您愿意,您可能可以这样做,但我不确定它是否在做您想要的事情,或者malloc’ed区域是否可以从主机以任何方式访问
如果您想要可变大小的动态设备分配,为什么不使用普通的cudamaloc方法?为什么使用设备符号?我不是说您无法以某种方式使其工作,但这不是实现的方法
编辑回答以下问题:
如果你想消除一个函数参数而使用一个设备变量,你可能可以让它工作,但这对我来说似乎是一个很大的麻烦,为了什么
无论如何,如果我觉得我真的需要这样做,我会这么做:
#include <stdio.h>
#define cudaCheckErrors(msg) \
do { \
cudaError_t __err = cudaGetLastError(); \
if (__err != cudaSuccess) { \
fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
msg, cudaGetErrorString(__err), \
__FILE__, __LINE__); \
fprintf(stderr, "*** FAILED - ABORTING\n"); \
exit(1); \
} \
} while (0)
float *V, *d_V;
__device__ float *V_d;
__global__ void my_kernel(){
printf("V[3] = %f\n", V_d[3]);
}
int main() {
int C=2;
int S=2;
V=(float *)calloc(S*C, sizeof(float));
V[0] = 0.0f;
V[3] = 4.0f;
cudaMalloc((void **)&d_V,C*S*sizeof(float));
cudaCheckErrors("malloc");
cudaMemcpy(d_V, V, C*S*sizeof(float), cudaMemcpyHostToDevice);
cudaCheckErrors("memcpy");
cudaMemcpyToSymbol(V_d,&d_V,sizeof(float *));
cudaCheckErrors("symbol");
my_kernel<<<1,1>>>();
cudaDeviceSynchronize();
cudaCheckErrors("kernel");
return 0;
}
#包括
#定义cudaCheckErrors(msg)\
做{\
cudaError\u t\u err=cudaGetLastError()\
如果(_err!=cudaSuccess){\
fprintf(标准,“致命错误:%s(%s位于%s:%d)\n”\
msg,cudaGetErrorString(_err)\
__文件(行)\
fprintf(stderr,“***失败-中止\n”)\
出口(1)\
} \
}而(0)
浮点数*V,*d_V;
__设备浮动*V\U d;
__全局\uuuu无效我的\u内核(){
printf(“V[3]=%f\n”,V_d[3]);
}
int main(){
int C=2;
int S=2;
V=(浮动*)calloc(S*C,sizeof(浮动));
V[0]=0.0f;
V[3]=4.0f;
Cudamaloc((无效**)和d_V,C*S*sizeof(浮动));
cudaCheckErrors(“malloc”);
cudaMemcpy(d_V,V,C*S*sizeof(float),cudaMemcpyHostToDevice);
cudaCheckErrors(“memcpy”);
cudaMemcpyToSymbol(V_d,&d_V,sizeof(float*);
cudaCheckErrors(“符号”);
我的内核();
cudaDeviceSynchronize();
cudaCheckErrors(“内核”);
返回0;
}
cuda memcheck报告了什么?不确定如何读取它。您正在某个地方取消引用空指针。您的意思是我不能直接分配\uuuu设备\uuuuuuu
变量?分配主机指针是唯一的方法?我倾向于消除向内核传递指针的需要。我还有一个可用的包装器,但认为它已损坏因为这一个没有产生任何错误!这到底是怎么打破的?!很好,谢谢你。你是对的,这样不值得麻烦。因为你还没有展示你的包装的代码,我无法回答“这到底是怎么打破的?”您可能想回顾良好的错误检查建议,或查看我张贴的例子,我也认为它是健壮的。
cudaGetErrorString(cudaMalloc(&V_d,C*S*sizeof(float)));
#include <stdio.h>
#define cudaCheckErrors(msg) \
do { \
cudaError_t __err = cudaGetLastError(); \
if (__err != cudaSuccess) { \
fprintf(stderr, "Fatal error: %s (%s at %s:%d)\n", \
msg, cudaGetErrorString(__err), \
__FILE__, __LINE__); \
fprintf(stderr, "*** FAILED - ABORTING\n"); \
exit(1); \
} \
} while (0)
float *V, *d_V;
__device__ float *V_d;
__global__ void my_kernel(){
printf("V[3] = %f\n", V_d[3]);
}
int main() {
int C=2;
int S=2;
V=(float *)calloc(S*C, sizeof(float));
V[0] = 0.0f;
V[3] = 4.0f;
cudaMalloc((void **)&d_V,C*S*sizeof(float));
cudaCheckErrors("malloc");
cudaMemcpy(d_V, V, C*S*sizeof(float), cudaMemcpyHostToDevice);
cudaCheckErrors("memcpy");
cudaMemcpyToSymbol(V_d,&d_V,sizeof(float *));
cudaCheckErrors("symbol");
my_kernel<<<1,1>>>();
cudaDeviceSynchronize();
cudaCheckErrors("kernel");
return 0;
}