Error Handling
Every CUDA API returns an error value of type cudaError_t
except for the kernel calls. They represent different exceptions and behaviors. const char *cudaGetErrorString(cudaError_t)
takes error and returns the respective error message. For example we can a good cudaDeviceSynchronize
call will handle its error to like,
const cudaError_t error = cudaDeviceSynchronize();
if (error != cudaSuccess) {
printf("code:%d, reason: %s\n", error, cudaGetErrorString(error));
exit(1);
}
And a good CUDA program will handle errors like this in each CUDA API call. For fairly moderate size program this becomes a huge mess of extra repeated lines of code and which should be replaced with a function or a macro. Professional CUDA-C Programming Book has a very good macro to handle this situation and that is,
// Copied from Book: Professional CUDA-C Programming
#define CHECK(call) \
{ \
const cudaError_t error = call; \
if (error != cudaSuccess) { \
printf("Error: %s:%d, ", __FILE__, __LINE__); \
printf("code:%d, reason: %s\n", error, cudaGetErrorString(error)); \
exit(1); \
} \
}
and the error checking code becomes,
See Qazalbash/CUDAForge/code/1_ArrSum/ArrSum.cu
for complete code example.