Мабуть, найкращий спосіб перевірити помилки в коді API часу виконання - це визначити функцію обробника стилю затвердження та макрос обгортки, як це:
#define gpuErrchk(ans) { gpuAssert((ans), __FILE__, __LINE__); }
inline void gpuAssert(cudaError_t code, const char *file, int line, bool abort=true)
{
if (code != cudaSuccess)
{
fprintf(stderr,"GPUassert: %s %s %d\n", cudaGetErrorString(code), file, line);
if (abort) exit(code);
}
}
Потім ви можете обернути кожен виклик API gpuErrchk
макросом, який буде обробляти стан повернення API, який він називає, наприклад:
gpuErrchk( cudaMalloc(&a_d, size*sizeof(int)) );
Якщо у виклику сталася помилка, буде надсилатися текстове повідомлення, що описує помилку, і файл та рядок у вашому коді, де сталася помилка, stderr
і програма вийде. Можна, можливо, змінити, gpuAssert
щоб створити виняток, а не викликати exit()
в більш досконалому додатку, якщо цього потрібно.
Другий пов'язаний питання полягає в тому, як перевірити помилки при запуску ядра, які не можуть бути безпосередньо загорнуті в макро-виклик, як стандартні дзвінки API виконання. Для ядер щось подібне:
kernel<<<1,1>>>(a);
gpuErrchk( cudaPeekAtLastError() );
gpuErrchk( cudaDeviceSynchronize() );
спочатку перевірять недійсний аргумент запуску, а потім змушують хоста чекати, поки ядро зупиниться, і перевірять помилку виконання. Синхронізацію можна усунути, якщо у вас є наступний блокуючий виклик API, такий:
kernel<<<1,1>>>(a_d);
gpuErrchk( cudaPeekAtLastError() );
gpuErrchk( cudaMemcpy(a_h, a_d, size * sizeof(int), cudaMemcpyDeviceToHost) );
у такому випадку cudaMemcpy
виклик може повернути або помилки, які виникли під час виконання ядра, або помилки із самої копії пам'яті. Це може бентежити початківця, і я рекомендую використовувати явну синхронізацію після запуску ядра під час налагодження, щоб легше зрозуміти, де можуть виникати проблеми.
Зауважте, що при використанні динамічного паралелізму CUDA дуже схожа методологія може бути та повинна застосовуватися до будь-якого використання API виконання CUDA в ядрах пристрою, а також після запуску ядра пристрою:
#include <assert.h>
#define cdpErrchk(ans) { cdpAssert((ans), __FILE__, __LINE__); }
__device__ void cdpAssert(cudaError_t code, const char *file, int line, bool abort=true)
{
if (code != cudaSuccess)
{
printf("GPU kernel assert: %s %s %d\n", cudaGetErrorString(code), file, line);
if (abort) assert(0);
}
}
getLastCudaError
іcheckCudaErrors
, які виконують майже все, що описано у прийнятій відповіді . Дивіться зразки для демонстрацій. Просто виберіть, щоб встановити зразки разом із інструментарієм, і у вас це буде.