2013-04-23 75 views
-2

原來的問題是推出更多的線程,它可能是這樣的:CUDA超過最大線程無錯誤?

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); 

退出是我錯過了一個自定義編寫的函數或東西嗎?

+2

你需要[檢查CUDA錯誤](http://stackoverflow.com/questions/14038589/what-is-the-canonical-way-to-check-for-errors-using-the-cuda-runtime -api)在每次內核啓動後。當您在啓動配置中超出塊或線程的最大數量時,您會收到「CUDA未指定的啓動錯誤」或其他問題。 – 2013-04-23 23:30:11

+0

@JaredHoberock我加了整個代碼。我(或者說nVidia的示例開發人員)似乎正在檢查每個可能步驟的錯誤。我缺少一個? – 2013-04-23 23:47:43

+2

是的。你不明白如何檢查內核啓動錯誤。請仔細閱讀Jared建議的鏈接。 – 2013-04-24 00:01:42

回答

3

內核啓動時可能出現兩類錯誤,需要按照特定的順序在單獨的步驟中檢查它們。

當進行內核調用並且在設備上實際啓動內核之前,第一類錯誤被同步報告,即這些是「預啓動」錯誤。這些錯誤通常涉及請求比可用的更多的特定資源(例如太多的共享內存,太多的線程)。內核調用後立即調用cudaGetLastError()來檢查這些。

第二類錯誤是在內核在設備上啓動後的某個時間點發生的錯誤(例如,內存訪問衝突,看門狗定時器超時)。這些是「發佈後」錯誤。內核調用一段時間後報告它們的原因是內核啓動異步發生的自然結果。他們在下一個機會中報告,這通常是下一個同步API調用。通過調用cudaDeviceSynchronize()檢查它們並檢查其狀態返回值。

發佈的代碼缺少對第一類錯誤的檢查。