故障排除#

使用 cuDNN 错误报告和 API 日志记录实用程序,以帮助解决使用 cuDNN 后端 API 开发的应用程序的问题。

错误报告和 API 日志记录#

cuDNN 错误报告和 API 日志记录是一个用于记录 cuDNN API 执行和错误信息的实用程序。对于每个 cuDNN API 函数调用,所有输入参数都会在 API 日志中报告。如果在 cuDNN API 执行期间发生错误,还可以报告错误条件的回溯信息,以帮助进行故障排除。此功能默认禁用,可以通过设置以下环境变量启用:CUDNN_LOGDEST_DBG CUDNN_LOGLEVEL_DBG。本节提供有关如何设置此日志记录的更多详细信息。

CUDNN_LOGLEVEL_DBG 可以设置为四个级别之一,这些级别与枚举 cudnnSeverity_t 的数值对齐。接受的数值为

  • 0:无错误,无性能损失

  • 1:错误

  • 2:警告和错误

  • 3:信息、警告和错误

超出范围的整数数值将被裁剪为 03,以较近者为准。

请注意,日志记录级别是嵌套的,因此启用较低级别的日志记录级别会包含更高级别的日志记录级别。旧版日志记录环境变量 CUDNN_LOGERR_DBGCUDNN_LOGWARN_DBGCUDNN_LOGINFO_DBG 已弃用,但在 v9 宽限期内将继续工作以保持兼容性。

日志输出包含变量名、数据类型、参数值、设备指针、进程 ID、线程 ID、cuDNN 句柄、CUDA 流 ID 以及元数据,例如函数调用发生的时间(以微秒为单位)。

在严重级别 3 下,日志将在每次公共 API 调用后包含一个条目(即“信息”日志记录),如下例所示

cuDNN (v90000) function cudnnSetActivationDescriptor() called:
    mode: type=cudnnActivationMode_t; val=CUDNN_ACTIVATION_RELU (1);
    reluNanOpt: type=cudnnNanPropagation_t; val=CUDNN_NOT_PROPAGATE_NAN (0);
    coef: type=double; val=1000.000000;
Time: 2024-01-21T14:14:21.366171 (0d+0h+1m+5s since start)
Process: 21264, Thread: 21264, cudnn_handle: NULL, cudnn_stream: NULL.

此日志记录将包含公共 API 名称和在 API 调用中使用的参数或属性(自 v8 起),以确认 cuDNN 已接收的内容。它还尝试提供有助于用户理解事件序列的基本信息,例如时间、进程、线程和流。

在严重级别 23 下,日志将包含警告,如下所示

CuDNN (v90100) function cudnnBackendFinalize() called:
        Warning: CUDNN_STATUS_NOT_SUPPORTED_SHAPE; Reason: Embedding dim per head for q and k is not a multiple of 8 at: d_qk % 8 != 0
        Warning: CUDNN_STATUS_NOT_SUPPORTED_SHAPE; Reason: generate_attention_desc()
        Warning: CUDNN_STATUS_NOT_SUPPORTED_SHAPE; Reason: generate_flash_fprop_mha_fort()
        Warning: CUDNN_STATUS_NOT_SUPPORTED_SHAPE; Reason: generate_mha_fort()
        Warning: CUDNN_STATUS_NOT_SUPPORTED_SHAPE; Reason: construct_fort_tree()
        Warning: CUDNN_STATUS_NOT_SUPPORTED_SHAPE; Reason: kernelGeneration()
        Warning: CUDNN_STATUS_NOT_SUPPORTED; Reason: ptr.isSupported()
        Warning: CUDNN_STATUS_NOT_SUPPORTED; Reason: engine_post_checks(*engine_iface, engine.getPerfKnobs(), req_size, engine.getTargetSMCount())
        Warning: CUDNN_STATUS_NOT_SUPPORTED; Reason: finalize_internal()
Time: 2024-03-07T14:56:33.925524 (0d+0h+0m+0s since start)
Process=1098828; Thread=1098828; GPU=NULL; Handle=NULL; StreamId=NULL.

除了警告或错误的状态代码枚举名称之外,日志还包含原因消息。对于许多警告和错误,库将提供更具解释性的消息,例如前面示例中的第一个警告。其他原因消息可能是从 cuDNN 源代码自动生成的,可能更难理解。随着时间的推移,我们计划在整个代码库中添加更多解释性消息。

回溯也包含在内,以提供额外的覆盖范围,其中函数调用的名称也可能在缺少纯英文消息的情况下提供提示。在回溯中,每个消息可能都有自己的严重性,并且仅在启用相应的严重性级别时才会报告。回溯消息以执行的相反顺序打印,因此顶部的消息将是根本原因,并且往往更有助于调试。前面的示例是警告回溯。以下示例是错误回溯。

cuDNN (v8300) function cudnnBackendFinalize() called:
    Info: Traceback contains 5 message(s)
        Error: CUDNN_STATUS_BAD_PARAM; reason: out <= 0
        Error: CUDNN_STATUS_BAD_PARAM; reason: is_valid_spacial_dim(xSpatialDimA[dim], wSpatialDimA[dim], ySpatialDimA[dim], cDesc.getPadLowerA()[dim], cDesc.getPadUpperA()[dim], cDesc.getStrideA()[dim], cDesc.getDilationA()[dim])
        Error: CUDNN_STATUS_BAD_PARAM; reason: is_valid_convolution(xDesc, wDesc, cDesc, yDesc)
        Error: CUDNN_STATUS_BAD_PARAM; reason: convolution.init(xDesc, wDesc, cDesc, yDesc)
        Error: CUDNN_STATUS_BAD_PARAM; reason: finalize_internal()
Time: 2021-10-05T17:11:07.935640 (0d+0h+0m+15s since start)
Process=87720; Thread=87720; GPU=NULL; Handle=NULL; StreamId=NULL.

有两种方法可以启用错误/警告报告和 API 日志记录,如下所述。为方便起见,日志输出可以由内置的默认回调函数处理,该函数会将输出定向到用户指定的日志文件或标准 I/O。用户还可以编写自己的回调函数以编程方式处理此信息,并使用 cudnnSetCallback() 传入他们自己的回调函数的函数指针。

方法 1:使用环境变量

要使用环境变量启用 API 日志记录,请按照以下步骤操作

  1. 将环境变量 CUDNN_LOGLEVEL_DBG 设置为 0123

  2. 将环境变量 CUDNN_LOGDEST_DBG 设置为 NULLstdoutstderr 或用户所需的文件路径。例如,/home/userName1/log.txt

  3. 在文件名中包含转换说明符。例如

    1. 要在文件名中包含日期和时间,请使用日期和时间转换说明符:log_%Y_%m_%d_%H_%M_%S.txt。转换说明符将在程序启动时自动替换为日期和时间,结果为 log_2017_11_21_09_41_00.txt

    2. 要在文件名中包含进程 ID,请使用 %i 转换说明符:log_%Y_%m_%d_%H_%M_%S_%i.txt,结果为:log_2017_11_21_09_41_00_21264.txt,当进程 ID 为 21264 时。当您运行多个进程时,使用进程 ID 转换说明符将防止这些进程同时写入同一文件。

    注意

    支持的转换说明符类似于 strftime 函数。如果文件已存在,日志将覆盖现有文件。

这些环境变量仅在初始化时检查一次。这些环境变量的任何后续更改在当前运行中均无效。另请注意,这些环境设置可以被下面的方法 2 覆盖。

使用环境变量进行 API 日志记录对性能的影响#

环境变量

CUDNN_LOGLEVEL_DBG=0

CUDNN_LOGLEVEL_DBG=1CUDNN_LOGLEVEL_DBG=2CUDNN_LOGLEVEL_DBG=3

CUDNN_LOGDEST_DBG 未设置

无日志输出,无性能损失

日志记录到 stderr,有少量性能损失

CUDNN_LOGDEST_DBG=NULL

无日志输出,无性能损失

无日志输出,无性能损失

CUDNN_LOGDEST_DBG=stdoutstderr

无日志输出,无性能损失

日志记录到 stdoutstderr,有少量性能损失

CUDNN_LOGDEST_DBG=filename.txt

无日志输出,无性能损失

日志记录到 filename.txt,有少量性能损失

方法 2:使用 API

要使用 API 函数调用来启用 API 日志记录,请参阅 cudnnSetCallback()cudnnGetCallback() 的 API 描述。

cudnnGetLastErrorString() 获取并清除最新的错误消息。在 cuDNN 库内部,消息存储在线程本地缓冲区中。