น่าจะเป็นวิธีที่ดีที่สุดในการตรวจสอบข้อผิดพลาดในรหัส API ของรันไทม์คือการกำหนดฟังก์ชั่นการจัดการสไตล์และยืนยันแมโคแรปเปอร์ดังนี้:
#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 Dynamic Parallelismวิธีการที่คล้ายกันมากสามารถและควรนำไปใช้กับการใช้งานของ CUDA runtime API ในเคอร์เนลของอุปกรณ์รวมถึงหลังจากที่เคอร์เนลของอุปกรณ์เปิดตัว:
#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
ทำสิ่งที่อธิบายไว้ในคำตอบที่ยอมรับได้ ดูตัวอย่างสำหรับการสาธิต เพียงแค่เลือกที่จะติดตั้งตัวอย่างพร้อมกับชุดเครื่องมือและคุณจะได้มัน