【CUDA编程】系列博客参考NVIDIA官方文档“CUDA C++ Programming Guide(v12.6)”。
本文为原创文章,未经本人允许,禁止转载。转载请注明出处。
1.Error Checking
同步函数在任务完成后才返回,这意味着host可以在函数返回时确信任务已经成功或失败。异步函数(见:Asynchronous Concurrent Execution)会在任务开始后立即返回,而不会等待任务完成。host无法在函数返回时直接知道任务是否成功完成。如果device上发生了异步错误(例如kernel在执行过程中出现非法内存访问),host端在调用异步函数时并不会立即得知该错误。这些错误会被推迟到后续某个CUDA API调用(可能与错误的任务毫无关联)时才被报告。
因此,唯一可以检查异步错误的方法是在异步函数调用之后立即通过调用cudaDeviceSynchronize()
(或使用Asynchronous Concurrent Execution中介绍的其他同步机制)进行同步,并检查由cudaDeviceSynchronize()
返回的错误码。
运行时为每个host线程维护一个错误变量,该变量被初始化为cudaSuccess
,每次发生错误(无论是参数验证错误还是异步错误)时都会被新的错误码所覆盖。cudaPeekAtLastError()
返回该变量,而cudaGetLastError()
返回该变量并将其重置为cudaSuccess
。
kernel启动不会返回任何错误码,因此需要在kernel启动后立即调用cudaPeekAtLastError()
或cudaGetLastError()
来检索任何启动前的错误。为了确保由cudaPeekAtLastError()
或cudaGetLastError()
返回的任何错误不是在kernel启动之前调用其他函数引起的,应在kernel启动前调用cudaGetLastError()
将运行时错误变量设置为cudaSuccess
。如果直接在kernel启动之后调用cudaPeekAtLastError()
或cudaGetLastError()
,host线程可能无法捕获device上发生的错误,因为此时kernel任务可能还未完成。在调用cudaPeekAtLastError()
或cudaGetLastError()
之前,必须确保device上的kernel任务已经完成,因此需要使用cudaDeviceSynchronize()
等同步机制。
注意,由cudaStreamQuery()
和cudaEventQuery()
返回的cudaErrorNotReady
不被视为错误,因此不会被cudaPeekAtLastError()
或cudaGetLastError()
报告。