Вероятно, лучший способ проверить наличие ошибок в коде API времени выполнения - это определить функцию-обработчик стиля assert и макрос-обертку следующим образом:
#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
который в значительной степени соответствует описанному в принятом ответе . Смотрите образцы для демонстраций. Просто установите образцы вместе с инструментарием, и он у вас будет.