-2

元の問題は、次のように可能なスレッドをさらに起動することでした。

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

カーネル呼び出しエラーを検出する方法がわからなかったため、エラーを検出しませんでした。これは、この質問のタロンミーの回答でよく説明されています。

CUDA ランタイム 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);

exit はカスタム作成関数ですか、それとも私が見逃したものですか?

4

1 に答える 1

3

カーネルの起動で発生する可能性のあるエラーには 2 つのクラスがあり、特定の順序に従って個別の手順でチェックする必要があります。

エラーの最初のクラスは、カーネル呼び出しが行われたとき、カーネルがデバイス上で実際に起動される前に同期的に報告されます。つまり、これらは「起動前」エラーです。これらのエラーは通常、利用可能な以上の特定のリソースを要求することを伴います (共有メモリが多すぎる、スレッドが多すぎるなど)。カーネル呼び出しの直後に cudaGetLastError() を呼び出して、これらを確認してください。

2 番目のクラスのエラーは、カーネルがデバイス上で起動された後のある時点で発生するものです (メモリ アクセス違反、ウォッチドッグ タイマーのタイムアウトなど)。これらは「起動後」のエラーです。カーネル呼び出しのしばらく後に報告される理由は、カーネルの起動が非同期で発生する自然な結果です。それらは次の機会 (通常は次の同期 API 呼び出し) で報告されます。これらを確認するには、cudaDeviceSynchronize() を呼び出し、そのステータス リターンを調べます。

投稿されたコードには、最初のクラスのエラーのチェックがありません。

于 2013-04-24T05:12:37.590 に答える