Mungkin cara terbaik untuk memeriksa kesalahan dalam kode API runtime adalah dengan mendefinisikan fungsi penangan gaya tegas dan pembungkus makro seperti ini:
#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);
}
}
Anda kemudian dapat membungkus setiap panggilan API dengan gpuErrchk
makro, yang akan memproses status pengembalian dari panggilan API yang dibungkus, misalnya:
gpuErrchk( cudaMalloc(&a_d, size*sizeof(int)) );
Jika ada kesalahan dalam panggilan, pesan teks yang menggambarkan kesalahan dan file dan baris dalam kode Anda di mana kesalahan terjadi akan dipancarkan ke stderr
dan aplikasi akan keluar. Anda dapat memodifikasi gpuAssert
untuk meningkatkan pengecualian daripada memanggil exit()
aplikasi yang lebih canggih jika diperlukan.
Pertanyaan kedua yang terkait adalah bagaimana memeriksa kesalahan dalam peluncuran kernel, yang tidak dapat langsung dibungkus dengan panggilan makro seperti panggilan API runtime standar. Untuk kernel, kira-kira seperti ini:
kernel<<<1,1>>>(a);
gpuErrchk( cudaPeekAtLastError() );
gpuErrchk( cudaDeviceSynchronize() );
pertama-tama akan memeriksa argumen peluncuran yang tidak valid, kemudian memaksa host untuk menunggu sampai kernel berhenti dan memeriksa kesalahan eksekusi. Sinkronisasi dapat dihilangkan jika Anda memiliki panggilan API pemblokiran berikutnya seperti ini:
kernel<<<1,1>>>(a_d);
gpuErrchk( cudaPeekAtLastError() );
gpuErrchk( cudaMemcpy(a_h, a_d, size * sizeof(int), cudaMemcpyDeviceToHost) );
dalam hal ini cudaMemcpy
panggilan dapat mengembalikan kesalahan yang terjadi selama eksekusi kernel atau dari salinan memori itu sendiri. Ini bisa membingungkan bagi pemula, dan saya akan merekomendasikan menggunakan sinkronisasi eksplisit setelah peluncuran kernel selama debugging untuk membuatnya lebih mudah untuk memahami di mana masalah mungkin timbul.
Perhatikan bahwa ketika menggunakan CUDA Dynamic Parallelism , metodologi yang sangat mirip dapat dan harus diterapkan pada penggunaan API runtime CUDA di kernel perangkat, serta setelah kernel perangkat diluncurkan:
#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
dancheckCudaErrors
, yang melakukan cukup banyak seperti yang dijelaskan dalam jawaban yang diterima . Lihat contoh untuk demonstrasi. Cukup pilih untuk menginstal sampel bersama dengan toolkit dan Anda akan memilikinya.