Deep Learning Performance Background
date
Jan 27, 2025
slug
nvidia-dl-perf-background
status
Published
tags
MLSys
summary
type
Post
TL; DR
本文总结了 GPU performance 和 Matrix Multiplication 的一些背景知识,参考 NVIDIA Deep Learning Performance.
GPU Performance
GPU Architecture

- 一块 GPU 上有多个 SM (streaming multiprocessor)
- 每个 SM 上有多个计算单元,有自己的一组寄存器,L1 cache
- 同一个 GPU 上的多个 SM 共用 L2 cache,以及一个全局内存(high bandwidth memory, HBM,也就是显存)
- multiply-and-add 操作是 GPU 执行的最多的操作,一个 multiply-and-add 包括两个浮点数操作。
- 目前的 GPU 有 cuda core 和 tensor core,其中 tensor core 更 specialized 到执行矩阵乘法,且面对比较短的数据类型的时候计算的吞吐量远大于 cuda core.
GPU Execution Model

- 和 CPU 不同,GPU 简化了控制单元,把空间投入到更多更小的计算单元上,以达到较高的并行计算能力。
- GPU 以一种 SIMT 的方式来执行函数,同样的逻辑会被不同的线程在不同的数据单元上执行。
- 和 GPU 的两级存储结构类似,线程的执行模型也被分为两级结构: threads 被组织为 block, block 会被映射到 SM 上执行;而 block 又被组织为 grid,每个 grid 会被映射到一个 gpu 上执行。
- GPU 通过切换到其他线程执行来隐藏指令依赖延迟,因此,为了提高 GPU 的利用率,我们需要 oversubscribe,也就是发起的线程数量要远大于 GPU 上计算单元 core 的数量。
Understanding Performance
一个函数在处理器(cpu, gpu, etc.)上的执行通常有三个主要的限制因素:
- 内存访问
- 数学运算
- 延迟
在 GPU 上,假设我们将内存访问操作和数学运算操作尽可能 overlap 起来,那么限制因素就变为内存访问和数学运算操作中较长的那个。
当数学运算操作成为瓶颈,那么这个程序是 math limited,否则是 memory limited。
也就是,当:
程序是 math limited。给定了硬件之后,数学运算带宽和内存访问带宽都成为确定的常数,上述条件也可以写作:
上式的左边的比值称为 arithmetic intensity,和程序中使用的算法的设计有关,当 arithmetic intensity 大于右边的阈值,则程序是 math limited,反之是 memory limited。需要注意的是,我们假设了程序有足够的 parallelism,通过 overlap 隐藏了延迟,若 workload 不够大,上述的推理并不成立。
DNN Operations
现代深度神经网络中使用的运算,根据运算的性质,大致可以归类到以下的三种:
- element-wise operation: 比如各种激活函数,矩阵加法,矩阵和标量相乘等。每个位置上的元素运算是独立的。element-wise operations 大多是 memory limited,因为通常都是把所有元素读取进来,然后做一些简单的运算之后又写回去,也就是 比较小。
- reduction operation: reduction operation 在计算每个位置的输出时需要访问输入中某个范围内的元素,比如 pooling,softmax 等。常见的 reduction 操作的 arithmetic intensity 比较低,通常也是 memory limited.
- dot product operation: 这类操作包括矩阵乘法,以及可以被表示为矩阵乘法的操作,比如卷积。通常来说,当参与运算的矩阵足够大时,这类操作时 math limited 的,但是当参与运算的矩阵很小时也可能是 memory limited 的,比如,使用一个矩阵乘一个向量。
Summary
要高效地利用 GPU,主要需要考虑以下方面:
- GPU 的硬件参数,计算
- 算法的设计,计算 arithmetic intensity,判断是 math limited 还是 memory limited
- workload 是否够大,使得能够 oversubscribe
Matrix Multiplication
GEMM (General Matrix Multiplication) Background
- GEMM 是现代深度神经网络中最重要的基本运算单元之一。
- GEMM 的形式: ,当 时,就是普通的矩阵乘法,当 时,可以看作是融合了 linear layer 和 skip connection
Arithmetic Intensity of GEMM
假设输入矩阵 A 的维度时 MxK, B 的维度是 KxN, 当考虑 GEMM 的 arithmetic intensity 时,当 K 较大时,系数可以忽略不计,主要的贡献来自 AB 这项。假设运算的精度是 t bytes,比如当 t 为 1 可以是 INT8, 当 t 为 2 可能是 FP16. 在计算每个输出元素时,包含一个 multiply-and-accumulate 操作,也就是两个浮点运算,因此:
GEMM GPU Implementation

GPU 上的 GEMM 通过 tiling 优化实现,tiling 提高效率的原因在于用空间换时间,对于一次读取的元素进行了多次运算,提高了 arithmetic intensity.
TensorCore Requirement
Tensor core 是更 specialize 到 GEMM 上的运算单元,使用 tensor core 进行 GEMM 运算能够达到远超 cuda core 的吞吐量。在使用 tensor core 时,矩阵的每个维度上的大小是 16 bytes 的倍数能够取得更好的效果(对于某些 gpu 这个数字可能不一样,需要查阅具体文档,比如对于 a100 是 128 bytes)。这个对齐要求在老版的 cuBLAS 是必须的,但是在新版中不是强制要求。
Dimension Quantization Effect
Tile Quantization
当参与运算的矩阵维度不能被 tiling factor 整除的时候,维度的最后可能出现一个只有很少有效元素的 tile,有效的运算量减少了。这时会导致 GPU 的有效利用率降低。下图展示了这种情况带来的影响。可以看到当 tile 的数量一样的时候 duration 时间都相同,当 tiling factor 没法整除矩阵维度时 flops 跳跃下降。

Wave Quantization
类似地,当一个执行一个 kernel 发起的 block 的数量不是 GPU 的 SM 数量的整数倍数的时候,最后一个 wave 会有若干 SM 空转,造成利用率下降。