Có lẽ cách tốt nhất để kiểm tra lỗi trong mã API thời gian chạy là xác định hàm xử lý kiểu xác nhận và macro trình bao bọc như thế này:
#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);
}
}
Sau đó, bạn có thể bao bọc từng lệnh gọi API bằng gpuErrchk
macro, sẽ xử lý trạng thái trả về của lệnh gọi API, ví dụ:
gpuErrchk( cudaMalloc(&a_d, size*sizeof(int)) );
Nếu có lỗi trong cuộc gọi, một tin nhắn văn bản mô tả lỗi và tệp và dòng trong mã của bạn nơi xảy ra lỗi sẽ được phát ra stderr
và ứng dụng sẽ thoát. Bạn có thể sửa đổi gpuAssert
một cách có thể hình dung để đưa ra một ngoại lệ thay vì gọi exit()
trong một ứng dụng phức tạp hơn nếu được yêu cầu.
Một câu hỏi liên quan thứ hai là làm thế nào để kiểm tra lỗi trong các lần khởi chạy kernel, không thể được gói trực tiếp trong một lệnh gọi macro như các lệnh gọi API thời gian chạy tiêu chuẩn. Đối với hạt nhân, một cái gì đó như thế này:
kernel<<<1,1>>>(a);
gpuErrchk( cudaPeekAtLastError() );
gpuErrchk( cudaDeviceSynchronize() );
trước tiên sẽ kiểm tra đối số khởi chạy không hợp lệ, sau đó buộc máy chủ phải đợi cho đến khi kernel dừng lại và kiểm tra lỗi thực thi. Đồng bộ hóa có thể được loại bỏ nếu bạn có lệnh gọi API chặn tiếp theo như sau:
kernel<<<1,1>>>(a_d);
gpuErrchk( cudaPeekAtLastError() );
gpuErrchk( cudaMemcpy(a_h, a_d, size * sizeof(int), cudaMemcpyDeviceToHost) );
trong trường hợp đó, cudaMemcpy
cuộc gọi có thể trả về một trong hai lỗi xảy ra trong quá trình thực thi kernel hoặc những lỗi từ chính bộ nhớ sao chép. Điều này có thể gây nhầm lẫn cho người mới bắt đầu và tôi khuyên bạn nên sử dụng đồng bộ hóa rõ ràng sau khi khởi chạy kernel trong quá trình gỡ lỗi để dễ hiểu vấn đề có thể phát sinh ở đâu.
Lưu ý rằng khi sử dụng CUDA Dynamic Parallelism , một phương pháp rất giống nhau có thể và nên được áp dụng cho bất kỳ việc sử dụng API thời gian chạy CUDA nào trong các hạt nhân thiết bị, cũng như sau khi bất kỳ kernel thiết bị nào khởi chạy:
#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
vàcheckCudaErrors
, thực hiện khá nhiều những gì được mô tả trong câu trả lời được chấp nhận . Xem các mẫu cho các cuộc biểu tình. Chỉ cần chọn để cài đặt các mẫu cùng với bộ công cụ và bạn sẽ có nó.