CUDA超过最大线程没有错误?

时间:2013-04-23 23:22:24

标签: visual-studio-2010 cuda parallel-processing

最初的问题是启动更多线程,这可能是这样的:

someKernel<<<1 , 1025>>> ( ... );

并没有检测到错误,因为我不知道如何检测内核调用错误。这个问题在talonmies中很好地解释了这个问题:

What is the canonical way to check for errors using the CUDA runtime API?

我没有修改我提供的代码,而是为了简洁而编写了自己的代码:

#include "cuda_runtime.h"
#include "device_launch_parameters.h"

#include <stdio.h>

#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
inline void gpuAssert(cudaError_t cudaError, char *file, int line, bool abort=true)
{
   if (cudaError != cudaSuccess) 
   {
      fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(cudaError), file, line);
   }
}

__global__ void addKernel(const int *dev_a, const int *dev_b, int *dev_c)
{
    int i = threadIdx.x;
    if ( i < 5 )
        dev_c[i] = dev_a[i] + dev_b[i];
}

int main()
{
    const int arraySize = 5;
    const int a[arraySize] = { 1, 2, 3, 4, 5 };
    const int b[arraySize] = { 10, 20, 30, 40, 50 };
    int c[arraySize] = { 0 };

    int *dev_a(nullptr), *dev_b(nullptr), *dev_c(nullptr);

    gpuErrchk( cudaMalloc((void**)&dev_a, arraySize * sizeof(int)) );
    gpuErrchk( cudaMalloc((void**)&dev_b, arraySize * sizeof(int)) );
    gpuErrchk( cudaMalloc((void**)&dev_c, arraySize * sizeof(int)) );

    gpuErrchk( cudaMemcpy(dev_a, a, arraySize * sizeof(int), cudaMemcpyHostToDevice) );
    gpuErrchk( cudaMemcpy(dev_b, b, arraySize * sizeof(int), cudaMemcpyHostToDevice) );

    const int testMax1D = 1025; 
    dim3 testMax2D ( 32, 33 );

    addKernel<<<1, testMax2D>>> ( dev_a , dev_b, dev_c );
    gpuErrchk( cudaPeekAtLastError() );
    gpuErrchk( cudaDeviceSynchronize() );

    gpuErrchk(  cudaMemcpy( c, dev_c, arraySize * sizeof(int), cudaMemcpyDeviceToHost) );

    printf("{1,2,3,4,5} + {10,20,30,40,50} = {%d,%d,%d,%d,%d}\n",
        c[0], c[1], c[2], c[3], c[4]);

    cudaFree(dev_a);
    cudaFree(dev_b);
    cudaFree(dev_c);

    return 0;
}

我现在得到正确的错误报告。感谢您的耐心等待。

我不理解gpuAssert函数中的这个调用,所以我省略了它:

if (abort) exit(code);

是退出自定义书面函数还是我错过的东西?

1 个答案:

答案 0 :(得分:3)

内核启动时可能会出现两类错误,需要按照特定的顺序在不同的步骤中检查它们。

在进行内核调用时以及在内核实际在设备上启动之前,同步报告第一类错误,即这些是“预启动”错误。这些错误通常涉及请求比可用资源更多的特定资源(例如,共享内存太多,线程太多)。在内核调用之后立即调用cudaGetLastError()来检查这些。

第二类错误是在内核在设备上启动后的某个时间点发生的错误(例如,内存访问冲突,监视程序计时器超时)。这些是“发布后”错误。它们在内核调用后的某个时间报告的原因是内核启动异步发生的自然结果。它们会在下一次机会报告,这通常是下一个同步API调用。通过调用cudaDeviceSynchronize()并检查其状态返回来检查这些。

发布的代码缺少检查第一堂课的错误。