我是一名CUDA初学者,他使用CUDA库(如CUFFT和CUBLAS)成功编译并运行了多个代码示例。然而,最近,我一直在尝试生成我自己的简单内核,并在调用我的内核后反复收到无意义的值。也就是说 - 当我将参数传递给内核时,在内核中设置其值,然后尝试将结果复制回主机并稍后读取值,它们是假的。我尝试了许多不同的简单教程内核,这些内核似乎适用于大多数人在线,但我总是得到荒谬的价值观。例如......
#define SIZE 10
// Kernel definition, see also section 4.2.3 of Nvidia Cuda Programming Guide
__global__ void vecAdd(float* A, float* B, float* C) {
// threadIdx.x is a built-in variable provided by CUDA at runtime
int i = threadIdx.x;
A[i]=0;
B[i]=i;
C[i] = A[i] + B[i];
}
int main {
int N=SIZE;
float A[SIZE], B[SIZE], C[SIZE];
float *devPtrA;
float *devPtrB;
float *devPtrC;
int memsize= SIZE * sizeof(float);
cudaMalloc((void**)&devPtrA, memsize);
cudaMalloc((void**)&devPtrB, memsize);
cudaMalloc((void**)&devPtrC, memsize);
cudaMemcpy(devPtrA, A, memsize, cudaMemcpyHostToDevice);
cudaMemcpy(devPtrB, B, memsize, cudaMemcpyHostToDevice);
// __global__ functions are called: Func<<< Dg, Db, Ns >>>(parameter);
vecAdd<<<1, N>>>(devPtrA, devPtrB, devPtrC);
cudaMemcpy(C, devPtrC, memsize, cudaMemcpyDeviceToHost);
for (int i=0; i<SIZE; i++)
printf("C[%d]=%f\n",i,C[i]);
cudaFree(devPtrA);
cudaFree(devPtrA);
cudaFree(devPtrA);
}
这是一个相当简单的问题;结果应该是:
C[0]=0.000000
C[1]=1.000000
C[2]=2.000000
C[3]=3.000000
C[4]=4.000000
C[5]=5.000000
C[6]=6.000000
C[7]=7.000000
C[8]=8.000000
C[9]=9.000000
然而,我的结果总是随机的,通常看起来更像:
C[0]=nan
C[1]=-32813464158208.000000
C[2]=nan
C[3]=-27667211200843743232.000000
C[4]=34559834084263395806523272811251761152.000000
C[5]=9214363188332593152.000000
C[6]=nan
C[7]=-10371202300694685655937271382147072.000000
C[8]=121653576586393934243511643668480.000000
C[9]=-30648783863808.000000
所以基本上,当我将参数传递到CUDA内核中以便将结果存储在其中以便复制回主机时,我倾向于抛弃垃圾。
这个真让我难过。任何帮助将不胜感激。
感谢。
答案 0 :(得分:2)
您应该始终检查API调用返回的错误。例如,C开发人员完全习惯于从malloc()检查NULL,因为不经常检查NULL会导致稍后的空指针解除引用(接着是坏事)。 C ++开发人员通常依赖于异常,但许多API都是C风格的(包括您正在使用的CUDA调用以及许多其他库),因此您应该知道何时检查错误。
理想情况下,您会检查每个API调用的错误。我个人不会使用CUTIL的SAFE_CALL宏,而是检查错误,正确处理它并抛出异常(C ++)或至少正确清理。这样,当您将实验扩展到更大的应用程序时,您已经考虑过错误处理。
至少,您应该在最后检查错误:
cudaError_t cudaResult;
cudaResult = cudaGetLastError();
if (cudaResult != cudaSuccess)
{
// Do whatever you want here
// I normally create a std::string msg with a description of where I am
// and append cudaGetErrorString(cudaResult)
}
答案 1 :(得分:1)
当我没有加载内核模块时,我在你的代码的Linux主机上得到了相同的行为?你确定你有驱动程序加载?您可以通过运行SDK附带的deviceQuery示例可执行文件来检查您是否拥有支持CUDA的设备。
作为更新,如果您已加载模块(使用lsmod验证)。您可能需要确保存在/ dev / nvidia *设备节点。入门指南中有一个示例脚本可以帮助您前进(第6页,http://developer.download.nvidia.com/compute/cuda/3_2_prod/docs/Getting_Started_Linux.pdf)。
进一步更新,如果你正在处理Tom提出的错误,你会发现这个错误。如果你想要一个快速而肮脏的方法,那将告诉你你在哪里遇到错误,你可以看一下CUDA的示例代码书(http://developer.nvidia.com/object/cuda-by -example.html)。该代码提供了一个HANDLE_ERROR,它将在程序遇到错误时终止程序,并在stdout上提供一条消息。这不是生产代码的最佳方法,但是快速而肮脏。
答案 2 :(得分:1)
我运行了你的代码并没有收到任何错误。我会试着看看sdk样本是否还在运行?此外,如果您需要GPUOcelot提供仿真支持(在这种情况下看起来有点过分)。
我的输出: cuda2:〜/ tests $ ./test C [0] = 0.000000 C [1] = 1.000000 C [2] = 2.000000 C [3] = 3.000000 C [4] = 4.000000 C [5] = 5.000000 C [6] = 6.000000 C [7] = 7.000000 C [8] = 8.000000 C [9] = 9.000000
答案 3 :(得分:1)
我终于弄明白了。我在64位Mac Pro上运行,并且已经将-Xcompiler“arch x86_64”作为参数传递给nvcc。 NVidia论坛上的主持人指出,在Mac上,我应该将“-m64”传递给nvcc。我一定在文档中错过了这个。传递-m64修复我的输出和内核似乎现在成功启动。感谢大家的回答。