Error Handling

Every CUDA runtime call returns cudaError_t.

Every CUDA runtime call returns cudaError_t. Kernel launches don't return errors directly — check with cudaGetLastError() (launch errors) and synchronization (execution errors).

Common errors:

too many threads per block, zero-sized grid out-of-bounds or invalid pointer access in a kernel too many registers/shared memory per block out of device memory compiled for the wrong -arch sticky errors (e.g., illegal address) corrupt the context — process must restart

Use compute-sanitizer (§33) to pinpoint memory errors.

#define CUDA_CHECK(call)                                                        \
    do {                                                                        \
        cudaError_t err__ = (call);                                             \
        if (err__ != cudaSuccess) {                                             \
            fprintf(stderr, "CUDA error %s at %s:%d: %s\n", #call, __FILE__,     \
                    __LINE__, cudaGetErrorString(err__));                       \
            exit(EXIT_FAILURE);                                                 \
        }                                                                       \
    } while (0)

CUDA_CHECK(cudaMalloc(&d_a, bytes));
kernel<<<grid, block>>>(d_a, n);
CUDA_CHECK(cudaGetLastError());          // invalid configuration, too many resources, ...
CUDA_CHECK(cudaDeviceSynchronize());     // errors during execution (illegal address, ...)