奇闻异事#

本节包含一系列随机主题和概念。

cuDNN 库配置#

cuDNN 以子库集合的形式交付。cuDNN 的默认用法需要所有子库;但是,可以删除某些子库,而 cuDNN 仍然可以工作,从而节省二进制文件大小,但会减少支持范围和性能。在此,我们记录了库的哪些子集是有效的配置。

配置通过环境变量 CUDNN_LIB_CONFIG 启用。下表列出了有效的配置。通过适当设置环境变量,您可以从 cuDNN 安装中删除除必需子库之外的所有子库。随着时间的推移,我们希望支持更多配置。

cuDNN 子库配置#

CUDNN_LIB_CONFIG 设置

摘要

必需的子库

FULL

cuDNN 的默认用法

全部

GRAPH_JIT_ONLY

支持仅限于图 API,仅使用 JIT 引擎(没有预编译内核)。

libcudnn.so, libcudnn_graph.so, libcudnn_engines_runtime_compiled.so - 不适用于静态库。

库概述 部分的 API 参考文档提供了关于子库分解和依赖关系图的更多详细信息。

FULL 配置#

这是 cuDNN 的默认用法。我们希望大多数用户继续使用此配置,除非他们想要探索二进制文件大小缩减的权衡。

GRAPH_JIT_ONLY 配置#

此配置提供

  • FULL 相比,显著减小二进制文件大小

  • 仅 JIT 引擎

  • 支持 NVIDIA Ampere 及更高版本的 GPU 架构

  • 图 API 的功能覆盖范围(在下面有一些注意事项)

  • 在许多情况下性能接近 FULL,但下面列出了注意事项

由于 GRAPH_JIT_ONLY 配置不包括带有预编译内核的引擎(这些内核位于最大的子库中),因此它与 FULL 相比,二进制文件大小显著减小。为了实现这种减小,请仅保留上表中必需的子库列中的库,并删除其余不需要的 cuDNN 子库。

这种减小二进制文件大小的权衡是,根据用例,您可能会看到与 FULL 相比的功能或性能差距。特别是,在某些情况下,您可能会由于缺少功能支持而看到运行时错误。特别是,这可能会发生在 专用预编译引擎 支持的图模式中。FULL 支持的所有其他图模式也受 GRAPH_JIT_ONLY 支持。

此外,对于功能上支持的模式,FULLGRAPH_JIT_ONLY 配置之间可能存在性能差异,具体取决于图模式和问题大小。作为粗略指导

  • 单算子 ConvolutionBwdFilter 平均而言存在较大的性能差距。

  • 单算子 Matmul 和单算子 ConvolutionBwdData 平均而言存在较小的性能差距。

  • 单算子 ConvolutionFwd 平均而言性能相当,但根据问题大小,您可能会看到性能差距。

  • 当迁移到 GRAPH_JIT_ONLY 时,多算子融合应具有相当的性能

这是 GRAPH_JIT_ONLY 的初始版本。我们正在积极努力缩小与 FULL 的差距。在未来,我们希望 GRAPH_JIT_ONLY 具有与 FULL 相同的图 API 功能覆盖范围,但对于某些在 FULL 中具有高度优化的预编译内核的特殊情况,性能可能存在一些差距。

注意

GRAPH_JIT_ONLY 支持 NVIDIA Ampere 及更高版本,但不支持 Ampere 之前的 GPU 架构。

子库配置说明#

由于 FULL 配置是默认配置,因此无需执行任何操作即可启用它。

要使用非默认配置(目前,唯一的非默认配置是 GRAPH_JIT_ONLY),请执行以下操作

  • 将环境变量 CUDNN_LIB_CONFIG 设置为 GRAPH_JIT_ONLY

  • 确保必需的子库位于 LD_LIBRARY_PATH(或 Windows 上的 PATH)中。

注意

GRAPH_JIT_ONLY 配置仅在使用 cuDNN 动态库时受支持,目前不适用于静态库。我们正在努力添加此支持。

线程安全#

cuDNN 库是线程安全的。只要线程不同时共享同一个 cuDNN 句柄,就可以从多个主机线程调用其函数。

在创建每个线程的 cuDNN 句柄时,建议在每个线程异步创建自己的句柄之前,首先同步调用一次 cudnnCreate()

根据 cudnnCreate(),对于从不同线程使用同一设备的多线程应用程序,推荐的编程模型是为每个线程创建一个(或几个,如果方便的话)cuDNN 句柄,并在线程的整个生命周期中使用该 cuDNN 句柄。

cuDNN 后端要求#

有关 cuDNN 后端的兼容版本,请参阅 支持的产品

SM Carveout#

从 cuDNN 8.9.5 开始,NVIDIA Hopper GPU 上支持 SM carveout,允许专业用户为单独 CUDA 流上的并发执行保留 SM。用户可以将目标 SM 计数设置为 cuDNN 启发式算法,并获取将在执行期间使用该数量 SM 的引擎配置列表。对于没有 cuDNN 启发式算法的高级用例,用户还可以从头开始创建引擎配置,并配置 SM carveout(下表中列出了支持此功能的引擎)。

以下代码片段是启发式用例的示例。

// Create heuristics descriptor
cudnnBackendDescriptor_t engHeur;
cudnnBackendCreateDescriptor(CUDNN_BACKEND_ENGINEHEUR_DESCRIPTOR, &engHeur);
cudnnBackendSetAttribute(engHeur, CUDNN_ATTR_ENGINEHEUR_OPERATION_GRAPH, CUDNN_TYPE_BACKEND_DESCRIPTOR, 1, &opGraph);
cudnnBackendSetAttribute(engHeur, CUDNN_ATTR_ENGINEHEUR_MODE, CUDNN_TYPE_HEUR_MODE, 1, &heurMode);
// SM carveout
int32_t targetSMCount = 66;
cudnnBackendSetAttribute(engHeur, CUDNN_ATTR_ENGINEHEUR_SM_COUNT_TARGET, CUDNN_TYPE_INT32, 1, &targetSMCount);
cudnnBackendFinalize(engHeur);
// Create engine config descriptor
cudnnBackendDescriptor_t engConfig;
cudnnBackendCreateDescriptor(CUDNN_BACKEND_ENGINECFG_DESCRIPTOR, &engConfig);
// Retrieve optimal engine config(s) from heuristics
cudnnBackendGetAttribute(engHeur, CUDNN_ATTR_ENGINEHEUR_RESULTS, CUDNN_TYPE_BACKEND_DESCRIPTOR, 1, &returnedCount, engConfig);
// "engConfig" should now be ready with target SM count as 66

此功能目前受正常卷积(FpropDgradWgrad)以及 Conv-Bias-Act 融合支持。

支持 SM Carveout 的 cuDNN 后端引擎#

卷积前向

卷积反向数据

卷积反向滤波器

cudnnConvolutionBiasActivationForward

  • 6

  • 58

  • 61

  • 62

  • 64

  • 65

  • 66

  • 67

  • 68

  • 69

  • 7

  • 63

  • 66

  • 67

  • 68

  • 69

  • 70

  • 71

  • 72

  • 73

  • 75

  • 76

  • 17

  • 62

  • 64

  • 65

  • 66

  • 68

  • 14

  • 39

  • 40

  • 41

  • 42

  • 43

原生 CUDA 图 API#

对于选定的引擎,cuDNN 现在提供了一种直接从执行计划和一组变体指针构建 CUDA 图(不要与 cuDNN 图混淆)的方法。这是一种比使用 CUDA 图捕获更灵活的替代方案,因为它允许使用新的变体包指针更新现有的 CUDA 图。与其他 CUDA 图一样,生成的图可以从不同的流中任意多次执行,并且可以作为较大 CUDA 图的子节点嵌入。

支持这些 API 的引擎具有行为注释 CUDNN_BEHAVIOR_NOTE_SUPPORTS_CUDA_GRAPH_NATIVE_API

C++ 和 Python API 都包含两个函数

  • populate_cuda_graph()

  • update_cuda_graph()

有关 C++ 中这些函数的示例用法,请参阅 cudagraphs.cpp 示例。