CUDA内核不断返回不良结果

时间:2011-02-14 20:41:59

标签: cuda gpu gpu-programming

我是一名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内核中以便将结果存储在其中以便复制回主机时,我倾向于抛弃垃圾。

这个真让我难过。任何帮助将不胜感激。

感谢。

4 个答案:

答案 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修复我的输出和内核似乎现在成功启动。感谢大家的回答。