Looking through the answers and comments on CUDA questions, and in the CUDA tag wiki, I see it is often suggested that the return status of every API call should checked for errors. The API documentation contains functions like cudaGetLastError
, cudaPeekAtLastError
, and cudaGetErrorString
, but what is the best way to put these together to reliably catch and report errors without requiring lots of extra code?
相关问题
- Achieving the equivalent of a variable-length (loc
- The behavior of __CUDA_ARCH__ macro
- Setting Nsight to run with existing Makefile proje
- Usage of anonymous functions in arrayfun with GPU
- Does CUDA allow multiple applications on same gpu
相关文章
- How to downgrade to cuda 10.0 in arch linux?
- What's the relation between nvidia driver, cud
- How can I use 100% of VRAM on a secondary GPU from
- NVidia CUDA toolkit 7.5.27 failing to install on O
- How can I find row to all rows distance matrix bet
- thrust: fill isolate space
- How to get the real and imaginary parts of a compl
- Matrix Transpose (with shared Memory) with arbitar
talonmies' answer above is a fine way to abort an application in an
assert
-style manner.Occasionally we may wish to report and recover from an error condition in a C++ context as part of a larger application.
Here's a reasonably terse way to do that by throwing a C++ exception derived from
std::runtime_error
usingthrust::system_error
:This will incorporate the filename, line number, and an English language description of the
cudaError_t
into the thrown exception's.what()
member:The output:
A client of
some_function
can distinguish CUDA errors from other kinds of errors if desired:Because
thrust::system_error
is astd::runtime_error
, we can alternatively handle it in the same manner of a broad class of errors if we don't require the precision of the previous example:The solution discussed here worked well for me. This solution uses built-in cuda functions and is very simple to implement.
The relevant code is copied below:
The C++-canonical way: Don't check for errors...use the C++ bindings which throw exceptions.
I used to be irked by this problem; and I used to have a macro-cum-wrapper-function solution just like in Talonmies and Jared's answers, but, honestly? It makes using the CUDA Runtime API even more ugly and C-like.
So I've approached this in a different and more fundamental way. For a sample of the result, here's part of the CUDA
vectorAdd
sample - with complete error checking of every runtime API call:Again - all potential errors are checked and reported via a thrown exception. This code uses my
Thin Modern-C++ wrappers for the CUDA Runtime API library (Github)
Note that the exceptions carry both a string explanation and the CUDA runtime API status code after the failing call.
A few links to how CUDA errors are automagically checked with these wrappers:
Probably the best way to check for errors in runtime API code is to define an assert style handler function and wrapper macro like this:
You can then wrap each API call with the
gpuErrchk
macro, which will process the return status of the API call it wraps, for example:If there is an error in a call, a textual message describing the error and the file and line in your code where the error occurred will be emitted to
stderr
and the application will exit. You could conceivably modifygpuAssert
to raise an exception rather than callexit()
in a more sophisticated application if it were required.A second related question is how to check for errors in kernel launches, which can't be directly wrapped in a macro call like standard runtime API calls. For kernels, something like this:
will firstly check for invalid launch argument, then force the host to wait until the kernel stops and checks for an execution error. The synchronisation can be eliminated if you have a subsequent blocking API call like this:
in which case the
cudaMemcpy
call can return either errors which occurred during the kernel execution or those from the memory copy itself. This can be confusing for the beginner, and I would recommend using explicit synchronisation after a kernel launch during debugging to make it easier to understand where problems might be arising.Note that when using CUDA Dynamic Parallelism, a very similar methodology can and should be applied to any usage of the CUDA runtime API in device kernels, as well as after any device kernel launches: