本系列主要介绍CUDNN 8之后版本推出的Graph模式,包括核心概念、Graph API的介绍、Op Fusion的介绍与代码示例等。
主要参考了cudnn的官方文档:NVIDIA cuDNN — NVIDIA cuDNN 9.0.0 documentation
概述
NVIDIA cuDNN 提供了 DNN 应用程序中频繁出现的操作的高度调整的实现:
- Convolution forward and backward, including cross-correlation
- Matrix multiplication
- Pooling forward and backward
- Softmax forward and backward
- Neuron activations forward and backward:
relu
,tanh
,sigmoid
,elu
,gelu
,softplus
,swish
- Arithmetic, mathematical, relational, and logical pointwise operations (including various flavors of forward and backward neuron activations)
- Tensor transformation functions
- LRN, LCN, batch normalization, instance normalization, and layer normalization forward and backward
在 cuDNN 版本 7 及更早版本中,API 旨在支持一组固定的操作(operation)和融合(fusion)模式,称为“legacy API”。从 cuDNN 版本 8 开始,为了解决快速扩展的流行融合模式集,添加了图形 API,允许用户通过定义操作图(operation graph)来表达计算,而不是通过从一组固定的 API 调用中进行选择。与旧版 API 相比,这提供了更好的灵活性,并且对于大多数用例来说,这是使用 cuDNN 的推荐方法。
cuDNN Handle
使用 cuDNN 的应用程序必须通过调用 cudnnCreate()
初始化库上下文的handle。该handle显式传递给对 GPU 数据进行操作的每个后续库函数。一旦应用程序结束使用cuDNN,它就可以使用 cudnnDestroy()
释放与handle关联的资源。这种方法允许用户在使用多个host thread、GPU 和 CUDA streams时显式控制库的功能。
Tensors and Layouts
Tensor Descripter
cuDNN 库使用通用 n 维张量描述符来描述数据,该描述符通过以下参数定义:
- 3 到 8 的多个维度
- 数据类型(32 位浮点、64 位浮点、16 位浮点……)
- 定义每个维度大小的整数数组
- 定义每个维度的步幅的整数数组(例如,要添加以到达同一维度的下一个元素的元素数量)
常见的Tensor Descriptor如下:
3-D Tensor Descriptor
3-D 张量常用于矩阵乘法,由三个字母组成:B、M、N。B 表示批量大小(对于单个 GEMM 设置为 1),M 表示行数,N代表列数。
4-D Tensor Descriptor
4-D 张量描述符用于定义具有 4 个字母的批量2D图像的格式:N、C、H、W 分别表示批量(batch)大小、特征图数量、高度和宽度。字母按步幅降序排列。常用的 4 维张量格式有:
- NCHW
- NHWC
- CHWN
5-D Tensor Descriptor
5-D 张量描述符用于定义批量 3D 图像的格式,用 5 个字母:N、C、D、H、W 分别表示批量大小、特征图数量、深度、高度和宽度。字母按步幅降序排列。常用的 5 维张量格式有:
- NCDHW
- NDHWC
- CDHWN
除此之外,还有包括Fully-Packed Tensors、Partially-Packed Tensors、Spatially Packed Tensors、Overlapping Tensors等类型。
Data Layout Formats
本节介绍 cuDNN 张量如何根据几种数据布局格式在内存中排列。
考虑一批具有以下尺寸的图像,数据从0到1279:
- N 是批量大小; 1
- C是特征图的数量(即通道数); 64
- H为像高; 5
- W为图像宽度; 4
NCHW Memory Layout
上述4D张量在内存中以NCHW格式排列如下:
- 从第一个channel (C=0) 开始,元素按行优先顺序连续排列。
- 继续第二个和后续channel,直到所有channel的元素都布置完毕。
- 继续进行下一batch(如果 N > 1)。
NHWC Memory Layout
对于NHWC内存布局,首先布局所有C channel中对应的元素,如下:
- 从channel 0 的第一个元素开始,然后继续到channel 1 的第一个元素,依此类推,直到所有 C channel的第一个元素都布局完毕。
- 接下来,选择channel 0 的第二个元素,然后继续选择channel 1 的第二个元素,依此类推,直到所有channel的第二个元素都布局完毕。
- 遵循channel 0 的行优先顺序并完成所有元素。
- 继续进行下一批(如果 N > 1)。
NC/32HW32 Memory Layout
NC/32HW32 与 NHWC 类似,但有一个关键区别。对于 NC/32HW32 存储器布局,64 个通道分为两组,每组 32 个channel - 第一组由channel由 c0 到 c31 组成,第二组由channel c32 到 c63 组成。然后使用 NHWC 格式对每个组进行布局。
MatMul Layouts
matmul 使用 3D 张量,并使用 BMN 维度进行描述。以下是推荐Layout的两个示例:
- Packed Row-major: dim [B,M,N] with stride [MN, N, 1]
- Packed Column-major: dim [B,M,N] with stride [MN, 1, M]