Logging
CUDA.jl can forward diagnostics from the CUDA driver and NVIDIA libraries to Julia's logging system. Use these messages to inspect API calls, investigate failures, and find performance hints.
Enabling logging
Start Julia with JULIA_DEBUG=CUDA to enable debug output across CUDA.jl and its libraries, including packages loaded separately, such as cuDNN and cuTENSOR:
JULIA_DEBUG=CUDA juliaFor less output, name individual packages. For example, JULIA_DEBUG=cuDNN enables cuDNN logging, and JULIA_DEBUG=CUDACore,cuBLAS enables CUDA.jl's core diagnostics, the driver log, and cuBLAS logging.
You can also toggle forwarding at run time:
cuDNN.enable_logging()
# ... calls to cuDNN ...
cuDNN.enable_logging(false)This setting applies process-wide. It does not change Julia's log level: the default logger only shows Info and above. To see traces, include the package in JULIA_DEBUG or use a logger that accepts Debug messages. Library logging can be expensive even when Julia filters out the messages, so disable forwarding in performance-sensitive code.
| Message | Level |
|---|---|
| Library errors and failure explanations | Error |
| Warnings | Warn |
| Performance hints | Info |
| API traces and kernel launches | Debug |
| Driver failure explanations | Debug |
The following packages provide enable_logging: CUDA (driver messages; requires a driver supporting CUDA 12.9 or newer), cuBLAS (including cuBLASLt), cuDNN, cuSPARSE, cuTENSOR, cuStateVec, and cuTensorNet. On Windows, cuBLAS forwarding covers cuBLASLt only. CUDA.enable_logging() controls the driver; it does not enable library logging.
cuSOLVER.enable_logging() requires a shared library that exports NVIDIA's logging API. If unavailable, it warns; use CUSOLVERDN_LOG_LEVEL as described below instead. cuFFT, cuRAND, CUPTI, and NVML have no equivalent library log forwarding.
Diagnosing errors
On drivers supporting CUDA 12.9 or newer, CuError exceptions include available driver explanations without enabling logging:
CUDA error: operation not supported (code 801, ERROR_NOT_SUPPORTED)
Driver log:
[12:34:56.789][1234][CUDA][E] ...
[12:34:56.789][1234][CUDA][E] Returning 801 (CUDA_ERROR_NOT_SUPPORTED) from cuModuleLoadDataExJULIA_DEBUG=CUDA also shows driver diagnostics for failures handled internally, such as an allocation retried after freeing memory or a driver failure inside a library. These messages do not necessarily mean your operation failed; check its return value or exception.
Capturing messages
Messages use the logger of the Julia task that triggered them. Messages from NVIDIA worker threads use the global logger. Delivery is asynchronous: call CUDA.flush_logs() before inspecting captured messages or closing a logger's output stream.
For example, to save cuBLAS diagnostics:
using CUDA, Logging
cuBLAS.enable_logging()
try
open("cublas.log", "w") do io
with_logger(SimpleLogger(io, Logging.Debug)) do
try
A = CUDA.rand(Float32, 16, 16)
A * A
finally
CUDA.flush_logs()
end
end
end
finally
cuBLAS.enable_logging(false)
endTo capture NVIDIA worker-thread messages too, install a global logger with Logging.global_logger. Custom loggers can select all CUDA diagnostics by their :CUDA group, or individual packages by the _module argument of handle_message.
Crash diagnostics
A crash can lose messages before Julia delivers them. For these cases, configure NVIDIA's own output before starting Julia. Leave Julia log forwarding disabled for those libraries, so it does not override their output settings.
| Library | Environment variables |
|---|---|
| CUDA driver | CUDA_LOG_FILE=stderr |
| cuBLAS | CUBLAS_LOGINFO_DBG=1 CUBLAS_LOGDEST_DBG=stderr |
| cuBLASLt | CUBLASLT_LOG_LEVEL=5 CUBLASLT_LOG_FILE=/dev/stderr |
| cuDNN | CUDNN_LOGLEVEL_DBG=3 CUDNN_LOGDEST_DBG=stderr |
| cuSPARSE | CUSPARSE_LOG_LEVEL=5 CUSPARSE_LOG_FILE=/dev/stderr |
| cuSOLVER | CUSOLVERDN_LOG_LEVEL=5 CUSOLVERDN_LOG_FILE=/dev/stderr |
| cuTENSOR | CUTENSOR_LOG_LEVEL=5 CUTENSOR_LOG_FILE=/dev/stderr |
| cuQuantum | CUSTATEVEC_LOG_LEVEL=5, CUTENSORNET_LOG_LEVEL=5 |
Replace /dev/stderr with a file path on systems without that device. cuQuantum's settings above write to standard output. These messages bypass Julia's logging filters and loggers. Log levels differ between libraries; consult NVIDIA's documentation for other settings.
API reference
CUDACore.enable_logging — Function
CUDA.enable_logging(enable::Bool=true)Forward the CUDA driver's log messages to Julia's logging system. Failure explanations are reported at Debug level and warnings at Warn level. This includes failures handled internally by CUDA.jl or a library. Requires a driver supporting CUDA 12.9 or newer.
Starting Julia with JULIA_DEBUG=CUDA enables this automatically and shows debug messages from all CUDA.jl packages. Calling this function only toggles driver log forwarding; it does not change Julia's log level or enable library logging. Use flush_logs to finish delivery before inspecting captured messages.
Driver explanations in CuError exceptions are available independently of this setting. For crash diagnostics, set CUDA_LOG_FILE before starting Julia to write logs directly.
CUDACore.flush_logs — Function
CUDA.flush_logs()Deliver queued driver and library messages to Julia's logging system, waiting for any ongoing delivery to finish. Call this before inspecting captured messages or closing a logger's output stream. This does not synchronize GPU work or enable logging.
cuBLAS.enable_logging — Function
cuBLAS.enable_logging(enable::Bool=true)Forward log messages from cuBLAS and cuBLASLt to Julia's logging system. API traces are reported at Debug level, performance hints at Info level, and problems at Warn or Error level. Starting Julia with JULIA_DEBUG=cuBLAS enables this automatically, and also shows the Debug-level messages.
cuDNN.enable_logging — Function
cuDNN.enable_logging(enable::Bool=true)Forward log messages from cuDNN to Julia's logging system. API traces are reported at Debug level, and problems (including the library's explanation of why a call failed) at Warn or Error level. Starting Julia with JULIA_DEBUG=cuDNN enables this automatically, and also shows the Debug-level messages.
cuSPARSE.enable_logging — Function
cuSPARSE.enable_logging(enable::Bool=true)Forward log messages from cuSPARSE to Julia's logging system. API and kernel traces are reported at Debug level, performance hints at Info level, and problems at Error level. Starting Julia with JULIA_DEBUG=cuSPARSE enables this automatically, and also shows the Debug-level messages.
cuSOLVER.enable_logging — Function
cuSOLVER.enable_logging(enable::Bool=true)Forward log messages from cuSOLVER to Julia's logging system. API and kernel traces are reported at Debug level, performance hints at Info level, and problems at Error level. Starting Julia with JULIA_DEBUG=cuSOLVER enables this automatically, and also shows the Debug-level messages.
If the installed shared library does not export the logging API, enabling emits a warning. Set CUSOLVERDN_LOG_LEVEL before starting Julia to use cuSOLVER's own output instead.
cuTENSOR.enable_logging — Function
cuTENSOR.enable_logging(enable::Bool=true)Forward log messages from cuTENSOR to Julia's logging system. API and kernel traces are reported at Debug level, performance hints at Info level, and problems at Error level. Starting Julia with JULIA_DEBUG=cuTENSOR enables this automatically, and also shows the Debug-level messages.
cuStateVec.enable_logging — Function
cuStateVec.enable_logging(enable::Bool=true)Forward log messages from cuStateVec to Julia's logging system. API and kernel traces are reported at Debug level, performance hints at Info level, and problems at Error level. Starting Julia with JULIA_DEBUG=cuStateVec enables this automatically, and also shows the Debug-level messages.
cuTensorNet.enable_logging — Function
cuTensorNet.enable_logging(enable::Bool=true)Forward log messages from cuTensorNet to Julia's logging system. API and kernel traces are reported at Debug level, performance hints at Info level, and problems at Error level. Starting Julia with JULIA_DEBUG=cuTensorNet enables this automatically, and also shows the Debug-level messages.