GPU 神经网Tensor Core 架构演进(四)

Tensor Core 基本原理

在英伟达的通用 GPU 架构中,主要存在三种核心类型:CUDA Core、Tensor Core 以及 RT Core。其中,Tensor Core 扮演着极其关键的角色。

Tensor Core 是针对深度学习和 AI 工作负载而设计的专用核心,可以实现混合精度计算并加速矩阵运算,尤其擅长处理半精度(FP16)和全精度(FP32)的矩阵乘法和累加操作。Tensor Core 在加速深度学习训练和推理中发挥着重要作用。

本节内容将通过三个层次逐步深入地探讨卷积与 Tensor Core 之间的关系、Tensor Core 的基础工作原理,以及 Tensor Core 架构的发展历程。同时结合实际代码示例,旨在帮助读者不仅能够理解在框架层面如何利用 Tensor Core 实现训练加速的具体细节,还能对 CUDA 编程有初步的了解。

这一系列内容将为读者揭开 Tensor Core 技术的神秘面纱,提供一个全面且条理清晰的认识。

发展历程

在我们深入探讨之前,先简要回顾一下英伟达 GPU 架构的演变历程。2006 年,英伟达发布 Tesla 架构,从此所有 GPU 都带有 CUDA Core,2017 年在 Volta 架构中首次提出 Tensor Core,2018 年在 Turing 架构中首次提出 RT Core。

在 GPU 中,处理核心通常被称为处理单元或处理器核心,用于执行计算任务。在英伟达的 GPU 架构中,在 Fermi 架构之前,处理核心被称为 Stream Processor(SPs)。这些 SPs 是用于执行并行计算任务的小型处理器,每个 SP 可以执行一个线程的计算任务。

2010 年,在 Fermi 架构中,英伟达对处理核心进行了改进和调整,引入了新的设计和特性,包括更好的线程调度和管理机制,更高效的内存访问模式,以及更多的可编程功能。在 Fermi 架构之后,英伟达将处理核心更名为 CUDA 核心,以强调其与 CUDA(计算统一设备架构)编程模型的紧密集成。

如图所示,在 Fermi 架构中其计算核心由 16 个 SM(Stream Multiprocesser)组成,每个 SM 包含 2 个线程束(Warp),一个 Warp 中包含 16 个 Cuda Core,共 32 个 CUDA Cores。每一个 Cuda Core 由 1 个浮点数单元 FPU 和 1 个逻辑运算单元 ALU 组成。

Nvida GPU 架构发展

由于 CUDA Core 在显卡里面是并行运算,也就是说大家分工计算。从逻辑上说,CUDA Core 越多,算力也就相应越强。所以说从 Fermi 架构开始,2012 年的 Kepler 架构和 2014 年的 Maxwell 架构,都在这个基础上疯狂加倍增加 Cuda Core。

到了 2016 年的 Pascal 架构,英伟达 GPU 开始往深度学习方向进行演进,NVLink 也是这个时候开始引入的。2017 年提出的 Volta 架构,引入了张量核 Tensor Core 模块,用于执行融合乘法加法,标志着第一代 Tensor Core 核心的诞生。

自从 Volta 架构搭载了首代 Tensor Core 以来,英伟达在每一次的架构升级中都不断对 Tensor Core 进行优化和更新,每一轮的更新都带来了新的变化和提升。接下来,我们将逐步深入介绍其原理和这些演进过程。

卷积计算

卷积运算是深度学习和神经网络中常用的一种操作,用于从输入数据中提取特征。卷积操作通常用于处理图像数据,但也可以应用于其他类型的数据,如语音、文本等。在深度学习中,卷积运算通常与激活函数(如 ReLU)、池化层等结合使用,构成卷积神经网络(CNN),用于提取并学习数据中的特征,从而实现图像识别、分类、分割等任务。Tensor Core 则是英伟达推出的一种专为加速深度学习中的矩阵计算而设计的硬件加速器,要理解卷积与 Tensor Core 之间的关系,我们需要先了解卷积运算的本质。

CNN vs GEMM

在深度学习中,卷积运算通常指的是利用一个小的、可学习的过滤器(或称为卷积核)在输入数据(如图像)上滑动,并在每个位置计算过滤器与其覆盖区域的元素逐点相乘后的总和,这个过程可以捕捉到局部特征。对于多通道输入,卷积运算会对每个通道执行此操作,并将结果累加起来得到最终的输出。当应用于图像处理时,这种机制使得卷积网络能够有效地识别图像中的边缘、纹理等特征。

卷积神经网络 CNN 一般包含许多卷积层,这些层通过卷积运算提取输入数据的特征。在算法层面上,卷积运算的加速通常涉及到一个关键步骤——数据重排,即执行 Im2Col 操作。

Im2Col 操作的目的是将卷积运算转换为矩阵乘法,这样做有几个显著的好处。首先,它允许利用已有的高效矩阵乘法算法(如 GEMM,General Matrix Multiply)来加速卷积计算。其次,这种转换可以减少重复的内存访问,因为在传统的卷积运算中,同一个输入元素可能会被多个卷积核重复使用。

Im2Col 是计算机视觉领域中将图片转换成矩阵的矩阵列(Column)的计算过程。由于二维卷积的计算比较复杂不易优化,因此在 AI 框架早期,Caffe 使用 Im2Col 方法将三维张量转换为二维矩阵,从而充分利用已经优化好的 GEMM 库来为各个平台加速卷积计算。最后,再将矩阵乘得到的二维矩阵结果使用 Col2Im 将转换为三维矩阵输出。

Img2col 算法主要包含两个步骤,首先使用 Im2Col 将输入矩阵展开一个大矩阵,矩阵每一列表示卷积核需要的一个输入数据,其次使用上面转换的矩阵进行 Matmul 运算,得到的数据就是最终卷积计算的结果。

卷积默认采用数据排布方式为 NHWC,输入维度为 4 维 (N, IH, IW, IC),卷积核维度为(OC, KH, KW , IC),输出维度为(N, OH, OW , OC)。

CNN 转换为 GEMM 计算

Im2Col 算法计算卷积的过程,具体简化过程如下:

  1. 将输入由 N×IH×IW×ICN×IH×IW×IC 根据卷积计算特性展开成 (OH×OW)×(N×KH×KW×IC)(OH×OW)×(N×KH×KW×IC) 形状二维矩;
    阵。显然,转换后使用的内存空间相比原始输入多约 KHxKW−1KHxKW−1 倍;
  2. 权重形状一般为 OC×KH×KW×ICOC×KH×KW×IC 四维张量,可以将其直接作为形状为 (OC)×(KH×KW×IC)(OC)×(KH×KW×IC) 的二维矩阵处理;
  3. 对于准备好的两个二维矩阵,将 (KH×KW×IC)作为累加求和的维度,运行矩阵乘可以得到输出矩阵(KH×KW×IC)作为累加求和的维度,运行矩阵乘可以得到输出矩阵(OH×OW)×(OC)$;
  4. 将输出矩阵 (OH×OW)×(OC)(OH×OW)×(OC) 在内存布局视角即为预期的输出张量 N×OH×OW×OCN×OH×OW×OC,或者使用 Col2Im 算法变为下一个算子输入 N×OH×OW×OCN×OH×OW×OC。

通过 Im2Col,输入数据被重排成一个大矩阵,而卷积权重(即卷积核)也被转换为另一个矩阵。这样,原本的卷积运算就转化为了这两个矩阵的乘法操作,如图上所示。这种转换后的矩阵乘法可以利用现代计算架构(如 Tensor Core)的强大计算能力,从而实现高效的计算加速。

而 GEMM(General Matrix Multiply,通用矩阵乘法)是一种高效的矩阵乘法算法,它特别适合于处理大规模的矩阵运算。在将卷积转换为矩阵乘法之后,多个这样的矩阵乘法计算可以被组织成单个更大的矩阵乘法运算来执行。这种方法称为批量处理,它可以进一步提升计算效率,因为它允许同时处理多个数据样本,从而更好地利用 GPU 等并行计算资源。

通过 Im2Col 操作和利用 GEMM 进行批量处理,卷积神经网络中的卷积层计算可以得到显著加速。这种加速不仅提高了模型训练的效率,也使得在实际应用中的推理过程更为迅速,为神经网络模型的开发和部署带来了实质性的好处。

混合精度训练

在深入探讨 Tensor Core 及其对深度学习训练加速的作用之前,我们首先需要明确一个关键概念———混合精度训练。这个概念的理解常常困扰许多人,有些人可能会直观地认为,混合精度训练意味着在网络模型中同时使用 FP16(半精度浮点数)和 FP32(单精度浮点数)。然而,这种字面上的理解并没有准确抓住混合精度训练的真正含义。

混合精度训练实际上是一种优化技术,它通过在模型训练过程中灵活地使用不同的数值精度来达到加速训练和减少内存消耗的目的。具体来说,混合精度训练涉及到两个关键操作:

  1. 计算的精度分配:在模型的前向传播和反向传播过程中,使用较低的精度(如 FP16)进行计算,以加快计算速度和降低内存使用量。由于 FP16 格式所需的内存和带宽均低于 FP32,这可以显著提高数据处理的效率。

  2. 参数更新的精度保持:尽管计算使用了较低的精度,但在更新模型参数时,仍然使用较高的精度(如 FP32)来保持训练过程的稳定性和模型的最终性能。这是因为直接使用 FP16 进行参数更新可能会导致训练不稳定,甚至模型无法收敛,由于 FP16 的表示范围和精度有限,容易出现梯度消失或溢出的问题。

FP32 vs FP16

而在混合精度的实现上,其通常需要特定的硬件支持和软件优化。例如,英伟达的 Tensor Core 就是专门设计来加速 FP16 计算的,同时保持 FP32 的累加精度,从而使得混合精度训练成为可能。在软件层面,AI 框架如 PyTorch 和 MindSpore 等也提供了混合精度训练的支持,通过自动化的工具简化了实现过程。可以从上图看出 FP16 相比于 FP32,不管是从整数位还是小数位来看,它所表示的范围要小很多。

软件层面混合精度计算

混合精度训练不仅仅是在模型中同时使用 FP16 和 FP32 那么简单,而是指在底层硬件算子层面,使用半精度(FP16)作为输入和输出,使用全精度(FP32)进行中间结果计算从而不损失过多精度的技术。这个底层硬件层面其实指的就是 Tensor Core,所以 GPU 上具备 Tensor Core 是使用混合精度训练加速的必要条件。

基本原理

初代 Tensor Core

当英伟达的架构演进到 Volta 架构时,标志着深度学习优化的重大突破。Volta 架构的一个显著特点是引入了大量的 Tensor Core,这一变化对于加速深度学习应用产生了革命性的影响。

Volta SM 架构图

在 Tensor Core 出现之前,CUDA Core 是实现深度学习加速的核心硬件技术。CUDA Core 可以处理各种精度的运算。如上图 Volta 架构图所示,左侧有 FP64、FP32 和 INT32 CUDA Cores 核心,右侧则是许多 Tensor Core 核心。

  • CUDA Core

尽管 CUDA Core 能够广泛地支持并行计算模式,它在执行深度学习中最常见的操作,如卷积(Conv)和矩阵乘法(GEMM)时仍然面临效率上的挑战。

具体来说,CUDA Core 在执行这些操作时,需要将数据在寄存器、算术逻辑单元(ALU)和寄存器之间进行多次搬运,这种过程既耗时又低效。此外,每个 CUDA Core 单个时钟周期只能执行一次运算,而且 CUDA Core 的数量和时钟速度都有其物理限制,这些因素共同限制了深度学习计算性能的提升。

  • Tensor Core

随着 Volta 架构的推出,英伟达引入了 Tensor Core,这是一种专为 AI 训练和推理设计的可编程矩阵乘法和累加单元。V100 GPU 中包含了 640 个 Tensor Core,每个流多处理器(SM)配备了 8 个 Tensor Core。相较于 CUDA Core,Tensor Core 能够在每个时钟周期内执行更多的运算,特别是它可以高效地完成矩阵乘法和累加操作两种操作是深度学习中最频繁和计算密集的任务之一。

通过利用 Tensor Core,V100 能够为 AI 训练和推理提供高达 125 Tensor TFLOPS 的算力。这种强大的性能,使得 V100 在处理深度学习任务时,相比于仅使用 CUDA Core 的早期架构,能够实现显著的加速。

Tensor Core 工作原理

在具体的运算过程中,Tensor Core 采用融合乘法加法(FMA)的方式来高效地处理计算任务。每个 Tensor Core 每周期能执行 4x4x4 GEMM,64 个浮点乘法累加(FMA)运算。

CNN 转换为 GEMM 计算

如上图所示,在执行运算 D=A*B+C,其中 A、B、C 和 D 是 4×4 矩阵。矩阵乘法输入 A 和 B 是 FP16 矩阵,而累加矩阵 C 和 D 可以是 FP16 或 FP32 矩阵。

具体来说,它首先接受两个 4x4 的 FP16 精度的输入矩阵 A 和 B,执行它们的矩阵乘法。然后,将这个乘法的结果与第三个 4x4 的矩阵 C 相加,其中矩阵 C 可以是 FP16 或 FP32 精度。最终,Tensor Core 输出一个新的 4x4 矩阵 D,该矩阵同样可以是 FP16 或 FP32 精度。

这也就实现了底层硬件上的混合精度计算。通过将矩阵乘法的输入限定为 FP16 精度,可以大幅减少所需的计算资源和内存带宽,从而加速计算。同时,通过允许累加矩阵 C 和输出矩阵 D 使用 FP32 精度,可以保证运算结果的准确性和数值稳定性。这种灵活的精度策略,结合 Tensor Core 的高效计算能力,使得在保持高性能的同时,还能有效控制神经网络模型的训练和推理过程中的资源消耗。

接下来我们再打开一层进一步探讨 Tensor Core 的运算能力。上文我们谈到在每个 Tensor Core 每个时钟执行 64 个 FP32 FMA 混合精度运算,一个 SM 中一共有 8 个 Tensor Core,所以每个时钟周期内总共执行 512 个浮点运算(8 个 Tensor Core × 64 个 FMA 操作/核)。

因此在 AI 应用中,Volta V100 GPU 的吞吐量与 Pascal P100 GPU 相比,每个 SM 的 AI 吞吐量提高 8 倍,此外得益于 Volta 架构在 SM 数量和核心设计上的优化,总体上共提高 12 倍。

Tensor Core 与 CUDA 编程

如图所示,在 CUDA 编程体系中,我们并非直接对线程进行控制,也就是图中的弯弯的线,而是通过控制一个 Warp,一个 Warp 包含很多线程(通常为 32 个线程),这些线程同时并行执行,利用 GPU 的并行计算能力。

Warp 与 Tensor Core 关系

在实际执行过程中,CUDA 会对 Warp 进行同步操作,确保其中的所有线程都达到同步点,并获取相同的数据。然后,这些线程将一起执行矩阵相乘和其他计算操作,通常以 16x16 的矩阵块为单位进行计算。最终,计算结果将被存储回不同的 Warp 中,以便后续处理或输出。

我们可以把 Warp 理解为软件上的一个大的线程概念,它帮助简化了对 GPU 并行计算资源的管理和利用。通过有效地利用 Warp 的并行性,CUDA 程序可以实现高效、快速的并行计算。

在 CUDA 程序执行过程中,我们可以通过线程的 Warp 来调度 Tensor Core 的执行。多个 Tensor Core 可以同时通过 Warp 内的线程来执行计算任务,利用 Tensor Core 提供的高性能矩阵运算能力。每个 Warp 内的线程可以利用 Tensor Core 执行 16x16x16 的矩阵运算,充分发挥 GPU 的计算潜能。

template<typename Use, int m, int n, int k, typename T, typename Layout=void> class fragment;

void load_matrix_sync(fragment<...> &a, const T* mptr, unsigned ldm);
void load_matrix_sync(fragment<...> &a, const T* mptr, unsigned ldm, layout_t layout);
void store_matrix_sync(T* mptr, const fragment<...> &a, unsigned ldm, layout_t layout);
void fill_fragment(fragment<...> &a, const T& v);
void mma_sync(fragment<...> &d, const fragment<...> &a, const fragment<...> &b, const fragment<...> &c, bool satf=false);

其中:

  • fragment:Tensor Core 数据存储类,支持 matrix_amatrix_b 和 accumulator

  • load_matrix_sync:Tensor Core 数据加载 API,支持将矩阵数据从 global memory 或 shared memory 加载到 fragment;

  • store_matrix_sync:Tensor Core 结果存储 API,支持将计算结果从 fragment 存储到 global memory 或 shared memory;

  • fill_fragment:fragment 填充 API,支持常数值填充;

  • mma_sync:Tensor Core 矩阵乘计算 API,支持 D = AB + C 或者 C = AB + C。

CUDA 通过CUDA C++ WMMA API向外提供了 Tensor Core 在 Warp 级别上的计算操作支持。这些 C++接口提供了专门用于矩阵加载、矩阵乘法和累加、以及矩阵存储等操作的功能。例如上图所示代码中,其中的 mma_sync 就是执行具体计算的 API 接口。借助这些 API,开发者可以高效地利用 Tensor Core 进行深度学习中的矩阵计算,从而加速神经网络模型的训练和推理过程。

一个 Tensor Core 每个周期可以执行 4x4x4 的 GEMM 运算。然而,在 CUDA 的层面,为什么提供了使用 16x16x16 的 GEMM 运算 API 呢?

Tensor Core 硬件原理

事实上,如果我们整体来看,如上图所示,一个 Tensor Core 是一个 4x4 的 Tensor Core 核心。但实际上,在一个 SM(Streaming Multiprocessor)中有多个 Tensor Core,我们无法对每个 Tensor Core 进行细粒度的控制,否则效率会很低。因此,一个 Warp 就扮演了重要角色,将多个 Tensor Core 打包在一起,以执行更大规模的计算任务。

通过 Warp 层的卷积指令,CUDA 向外提供了一个 16x16x16 的抽象层,使得开发者可以通过一条指令完成多个 Tensor Core 的协同工作,实现高效的并行计算。这条指令也即我们之前提到的mma_sync API,它允许开发者利用 Warp 内的线程同时调度多个 Tensor Core 执行矩阵乘加操作,从而提高 GPU 计算的效率和性能。

那么现在有一个问题,Tensor Core 是如何跟卷积计算或者 GEMM 计算之间进行映射的呢?

例如 GPU 中的 Tensor Core 一次仅仅只有 4x4 这么小的 kernel,怎么处理 input image 224∗224224∗224,kernel 7∗77∗7 的 GEMM 计算呢?

或者说在现在大模型时代,Tensor Core 是怎么处理 Transformer 结构 inputembedding 为 2048∗20482048∗2048,hiddensize 为 1024∗10241024∗1024 的 GEMM 呢?

上文我们已经提到,卷积运算可以被转化为矩阵乘法操作,这一点是连接卷积和 Tensor Core 的桥梁。

Tensor Core 硬件原理

在实际执行过程中,如上图中所示,蓝色矩阵和黄色矩阵的片段会被取出进行计算,即所谓的 Fragment。这些 Fragment 进行计算后形成 Fragment block,而这些 Fragment block 在 CUDA 编程模型中就是通过线程块(Thread block)的来组织执行的。在线程块内部的计算过程中,会进一步提取部分数据形成 Warp level 级别的计算,Warp level 的计算其实还是很大,于是在 Fragment 执行时会将其变为满足我们 Tensor Core 和矩阵输入的计算了。

小结与思考

  • Tensor Core 的核心作用:Tensor Core 是英伟达 GPU 中专门设计用于加速深度学习和 AI 任务的硬件单元,通过混合精度计算优化了矩阵乘法和累加操作的性能。

Te- nsor Core 的技术演进:自 Volta 架构首次引入后,Tensor Core 在英伟达 GPU 架构的后续迭代中不断得到优化,增加了支持的计算精度并提升了运算能力,以满足日益增长的 AI 计算需求。

  • Tensor Core 的工作机制:利用融合乘法加法(FMA)技术,Tensor Core 能在单周期内完成大量 FP16 矩阵乘法和 FP32 累加操作,通过 CUDA 编程模型中的 Warp 调度实现高效并行计算,加速神经网络模型的训练和推理过程。

自 Volta 架构时代起,英伟达的 GPU 架构已经明显地转向深度学习领域的优化和创新。2017 年,Volta 架构横空出世,其中引入的张量核心(Tensor Core)设计可谓划时代之作,这一设计专门针对深度学习计算进行了优化,通过执行融合乘法加法操作,大幅提升了计算效率。与前一代 Pascal 架构相比,Volta 架构在深度学习训练和推理方面的性能提升了 3 倍,这一飞跃性进步为深度学习的发展提供了强大的硬件支持。

英伟达 GPU Tensor Core 发展

紧随其后,在一年后的 2018 年,英伟达发布了 Turing 架构,进一步增强了 Tensor Core 的功能。Turing 架构不仅延续了对浮点运算的优化,还新增了对 INT8、INT4、甚至是 Binary(INT1)等整数格式的支持。这一举措不仅使大范围混合精度训练成为可能,更将 GPU 的性能吞吐量推向了新的高度,较 Pascal GPU 提升了惊人的 32 倍。此外,Turing 架构还引入了先进的光线追踪(RT Core)技术。

2020 年,Ampere 架构的推出再次刷新了人们对 Tensor Core 的认知。Ampere 架构新增了对 TF32 和 BF16 两种数据格式的支持,这些新的数据格式进一步提高了深度学习训练和推理的效率。同时,Ampere 架构引入了对稀疏矩阵计算的支持,在处理深度学习等现代计算任务时,稀疏矩阵是一种常见的数据类型,其特点是矩阵中包含大量零值元素。传统的计算方法在处理这类数据时往往效率低下,而 Ampere 架构通过专门的稀疏矩阵计算优化,实现了对这类数据的高效处理,从而大幅提升了计算效率并降低了能耗。此外,Ampere 架构还引入了 NVLink 技术,这一技术为 GPU 之间的通信提供了前所未有的高速通道。在深度学习等需要大规模并行计算的任务中,GPU 之间的数据交换往往成为性能瓶颈。而 NVLink 技术通过提供高带宽、低延迟的连接,使得 GPU 之间的数据传输更加高效,从而进一步提升了整个系统的计算性能。

到了 2022 年,英伟达发布了专为深度学习设计的 Hopper 架构。Hopper 架构标志性的变化是引入了 FP8 张量核心,这一创新进一步加速了 AI 训练和推理过程。值得注意的是,Hopper 架构去除了 RT Core,以便为深度学习计算腾出更多空间,这一决策凸显了英伟达对深度学习领域的专注和投入。此外,Hopper 架构还引入了 Transformer 引擎,这使得它在处理如今广泛应用的 Transformer 模型时表现出色,进一步巩固了英伟达在深度学习硬件领域的领导地位。

2024 年,英伟达推出了 Blackwell 架构为生成式 AI 带来了显著的飞跃。相较于 H100 GPU,GB200 Superchip 在处理 LLM 推理任务时,性能实现了高达 30 倍的惊人提升,同时在能耗方面也实现了高达 25 倍的优化。其中 GB200 Superchip 能够组合两个 Blackwell GPU,并与英伟达的 Grace 中央处理单元配对,支持 NVLink-C2C 互联。此外,Blackwell 还引入了第二代 Transformer 引擎,增强了对 FP4 和 FP6 精度的兼容性,显著降低了模型运行时的内存占用和带宽需求。此外,还引入了第五代 NVLink 技术,使每个 GPU 的带宽从 900 GB/s 增加到 1800 GB/s。

总的来说,从 Volta 到 Blackwell,英伟达的 GPU 架构经历了一系列针对深度学习优化的重大创新和升级,每一次进步都在推动深度学习技术的边界。这些架构的发展不仅体现了英伟达在硬件设计方面的前瞻性,也为深度学习的研究和应用提供了强大的计算支持,促进了 AI 技术的快速发展。

接下来,我们将逐一深入剖析每一代 Tensor Core 的独特之处,以揭示其背后的技术奥秘。

Turing 架构 Tensor Core

第一代 Tensor Core(Volta)

在开始介绍 Volta 架构中的第一代 Tensor Core 之前,我们先来了解一下 Volta 架构的实现细节。

Volta SM

如上图所示,左边就是 Volta SM 的架构图,Volta 架构中的 Streaming Multiprocessor(SM)通过引入子核心(Sub Core)概念,提升了其执行效率和灵活性。在 Volta 架构中,一个 SM 由 4 个 Sub Core 组成,每个 Sub Core 可以被视为一个更小的、功能完备的执行单元,它们共同工作以提高整体的处理能力。

每个 Sub Core 内部包含了一定数量的 CUDA 核心,这是英伟达 GPU 的基础计算单元,用于执行并行计算任务。除此之外,Sub Core 还集成了专门的整数(INT)和浮点(FP)运算单元,这些单元能够同时进行整数和浮点计算,从而提高计算效率。更重要的是,Sub Core 内还配备了一组张量核心(Tensor Core),这是 Volta 架构的核心创新之一,专为加速深度学习中的矩阵乘法和累加操作而设计,极大地提升了深度学习训练和推理的性能。

Volta SM 的结构揭示了其内部工作机制的细节。SM 顶部的 L1 指令缓存负责存储即将执行的指令,并将这些指令发送到下方的四个 Sub Core 中。这种指令传输是单向的,确保了指令能够高效、有序地分配给每个执行单元。

在 Sub Core 完成计算任务后,其与位于 SM 底部的 L1 数据缓存(L1 Cache)和共享内存(Shared Memory)之间的交互则是双向的。这种设计允许 Sub Core 不仅可以读取下一批计算所需的数据,还可以将计算结果写回缓存或共享内存中,供其他 Sub Core 或 SM 中的其他组件使用。这种灵活的数据交互机制优化了数据流动,减少了内存访问延迟,进一步提升了整体的计算效率。

Volta SM 微架构

接下来我们深入研究 Volta GPU 中的 SM,首先 SM 它在处理寄存器的整体读写逻辑方面起着核心作用,是计算的关键单元。其次在每个 SM 的 Sub-Core 中,包含了多种功能单元,如 Tensor Core(张量核心)、FP64、FP32、INT8 等 CUDA Core、RT Core 和特殊函数处理单元 MFU。

此外,每个 Sub-Core 中还设有 Warp Scheduler,它负责有效调度执行计算单元的工作。数据被存储在寄存器中,通过高效的调度和数据流,实现快速并行的数据处理和计算过程。

值得注意的是,每个 SM Sub-Core 内含有两个 4x4x4 Tensor Core。Warp Scheduler 向 Tensor Core 发送矩阵乘法 GEMM 运算指令。Tensor Core 接收来自寄存器文件的输入矩阵(A、B、C),执行多次 4x4x4 矩阵乘法操作,直至完成整个矩阵乘法,并将结果矩阵写回寄存器文件(Register File)中。

Volta SM 微架构

如上图所示,最上面是共享的 L1 缓存,每个时钟周期可以执行 4 个 Warp 指令,下属 4 个独立的 Sub Core 的数据是不进行缓存的,但是每个 Sub Core 里有两个 Tensor Core, 这两个 Tensor Core 中的数据是可以共享的,再往下有一个共享内存,每个时钟周期可以传输 128B 的数据,当所有的 SM 计算完这个权重矩阵就会将数据回传到 L2 Cache 中,最后返回 Host Cpu 中。

Sub Core 微架构

如图所示,在一个 Sub Core 内的微架构中,顶部依然是 L1 Cache,紧随其后的是 L0 Cache,也就是 Register File。Register File 负责将数据传输到 Warp Scheduler,而具体的指令调度则依赖于 Warp Scheduler。针对通用的矩阵计算任务,即 CUDA Core 计算,我们通过 Math Dispatch Unit 将指令分发到具体的 FP64、INT、FP32 和 MUFU 等执行单元进行计算。

Volta Sub Core 微架构

然而,当调用 WMMA 相关的 API 或指令时,Warp Scheduler 会直接触发 Tensor Core 中的计算,每个 Tensor Core 内含有两个 4x4x4 的矩阵,在每个时钟周期内并行进行计算,最终将结果存回 Register File 寄存器中。寄存器通过 MIO 的 Data Pipeline 与 Shared Memory 进行通信。

另外,在 Volta 架构中相比 P100 有一个重要改进,即将 L1 缓存和共享内存合并为同一块空间,其中的共享内存 SMEM 为整个 SM 提供了 96KB 的存储空间。对 L2 Cache 也进行了更新,性能提升了 5%到 15%。

因此,在 Volta 架构中,Sub Core 微架构单独提供了一个 Tensor Core 的指令,直接提供给 Warp Scheduler 使用,无需通过 Math Dispatch Unit 进行指令分发。

除了引入专门针对 AI 框架矩阵计算的 Tensor Core,Volta 架构还减少了指令延迟,进一步提高了计算效率。这些设计和优化使得 Volta 架构对 AI 和深度学习任务有着更快的处理速度。

第二代 Tensor Core(Turing)

在 Turing 架构中,我们直接进入 Sub Core(微内核)来了解第二代 Tensor Core。

Turing Sub Core 微架构

如上图所示,与之前的版本相比,Turing 架构的 Tensor Core 除了支持 FP16 类型之外,还增加了 INT8 和 INT4 等多种类型,这一变化使得 Turing 架构在处理不同精度的计算任务时更加得心应手。

此外,Turing 架构还引入了 FP16 的 FastPath,这一创新设计使得每个时钟周期可以执行高达 32 次的计算操作。与 Volta 架构中需要 4 到 8 个时钟周期才能完成单个多线程 GEMM 计算的情况相比,Turing 架构的计算频率和吞吐量得到了显著提升。

值得一提的是,Turing 架构还支持通过线程共享数据的本地内存(Local Memory)。换句话说,在 Turing 架构的 Tensor Core 层面,每个线程的私有寄存器被设计成了可共享的资源。通过一种透明的共享机制,Tensor Core 能够充分利用这些寄存器资源,实现更高效的矩阵计算。这种设计使得 Tensor Core 在执行矩阵乘法等计算密集型任务时,能够充分利用线程间的协作,提高计算效率,还降低了系统的整体能耗。

Turing 架构的第二代 Tensor Core 在距离上一代 Volta 架构仅一年的时间内推出,它不仅在数据类型支持上进行了扩展,还在计算效率和数据共享方面实现了优化更新。

第三代 Tensor Core(Ampere)

当谈及第三代 Tensor Core 的重大改变时,首先需要提到多级缓存和数据带宽方面的优化,下面我们就先来具体了解一下 GPU 中的多级带宽体系。

Ampere 多级带宽体系

如图所示为 Ampere 架构多级带宽体系,我们从下往上看,最下面为这次架构升级所引入 NVLink 技术,它主要来优化单机多块 GPU 卡之间的数据互连访问。在传统的架构中,GPU 之间的数据交换需要通过 CPU 和 PCIe 总线,这成为了数据传输的瓶颈。而 NVLink 技术允许 GPU 之间直接进行高速的数据传输,极大地提高了数据传输的效率和速度。

Ampere 多级带宽体系

接下来,再往上一层为 L2 Cache 缓存和 DRAM,它们负责的是每块 GPU 卡内部的存储。L2 Cache 缓存作为一个高速缓存,用于存储经常访问的数据,以减少对 DRAM 的访问延迟。DRAM 则提供了更大的存储空间,用于存储 GPU 计算所需的大量数据。这两者的协同工作,使得 GPU 能够高效地处理大规模数据集。这里要说明的一点是我们所说的 HBM 其实就是多个 DRAM 的堆叠,它通过堆叠多个 DRAM 芯片来提高带宽和容量。

再往上一层为共享内存和 L1 Cache,它们负责 SM 中数据存储,共享内存允许同一 SM 内的线程快速共享数据,通过共享内存,线程能够直接访问和修改共享数据,从而提高了数据访问的效率和并行计算的性能。L1 缓存,主要用于缓存 SM 中经常访问的数据和指令。

而最上面是针对具体的计算任务 Math 模块,负责 GPU 数学处理能力。Math 模块包括 Tensor Core 和 CUDA Core,分别针对不同的计算需求进行优化。Tensor Core 是专为深度学习等计算密集型任务设计的,能够高效地执行矩阵乘法等张量运算。而 CUDA Core 则提供了更广泛的计算能力,支持各种通用的 GPU 计算任务。

Movement Efficiently

在 A100 中,最显著的改进之一是"Movement Efficiently",即数据搬运效率的提升,实现了三倍的速度提升,这主要得益于 Ampere 架构引入的异步内存拷贝机制。

在 Ampere 之前的 GPU 架构中,如果要使用共享内存(Shared Memory),必须先把数据从全局内存(Global Memory)加载到寄存器中,然后再写入共享内存。这不仅浪费了宝贵的寄存器资源,还增加了数据搬运的时延,影响了 GPU 的整体性能。

Ampere 异步内存拷贝机制

如上图所示,Ampere 架构中提供异步内存拷贝机制,通过新指令 LDGSTS(Load Global Storage Shared),实现全局内存直接加载到共享内存,避免了数据从全局内存到寄存器再到共享内存的繁琐操作,从而减少时延和功耗。

另外,A100 还引入了软件层面的 Sync Copy,这是一种异步拷贝机制,可以直接将 L2 Cache 中的全局内存传输到 SMEM 共享内存,然后直接执行,减少了数据搬运带来的时延和功耗。

此外,Ampere 架构的 Tensor Core 还进行了优化,一个 Warp 提供了 32 个线程,相比于 Volta 架构中每个 Tensor Core 只有 8 个线程,这样的设计可以减少线程之间的数据搬运次数,从而进一步提高计算效率。综上所述,A100 相较于 V100 在数据处理和计算效率方面有了显著的提升。

Tensor Core FFMA

当我们深入研究 FFMA(Fuse Fold Math and Add)操作时,可以从下图中得到更多的信息。在这个图中,绿色的小块代表 Sub Core,也就是之前提到的 Sub Core,而图中连续的蓝色框代表寄存器 Registers。

Ampere FFMA

当寄存器仅使用 CUDA Core 时,所有数据都存储在寄存器中,每个寄存器针对一个 CUDA Core 进行数据传输。这样使用 CUDA Core 计算会非常慢。

在 V100 中,每个 Tensor Core 可以处理 8 个线程,每个线程拥有自己的寄存器。因此,在 8 个时钟周期内,可以执行 1024 次 MAC 操作。而在 A100 的 Tensor Core 中,每个 Tensor Core 可以处理 32 条线程,因此在 8 个时钟周期内,可以寄存 2048 次 MAC 操作,每个时钟周期处理其中一块的数据。

第三代 Tensor Core 的 Ampere 架构除了制造工艺的提升外,还提供了更多的线程,使硬件执行速度更快,数据传输更少,每个时钟周期的吞吐量更大。

观察这个图后,我们不禁要问:为什么使用 Tensor Core 比单纯使用 CUDA Core 执行更快呢?

针对矩阵计算而言,这是因为每次针对 Tensor Core 进行计算速度更快、处理更多数据、吞吐量更高。Tensor Core 的引入提高了计算效率,尤其在大规模矩阵计算中表现出色。

第四代 Tensor Core(Hopper)

2022 年英伟达提出的 Hopper 架构,这一创新架构中最为引人瞩目的便是第 4 代 Tensor Core 的亮相。

回顾 Tensor Core 的发展历程,前三代的 Tensor Core 均基于 Warp-Level 编程模式运作。尽管在英伟达 A100 架构中引入了软件的异步加载机制,但其核心运算逻辑仍基于 Warp-Level 编程模式进行。简而言之,这一模式要求先将数据从 HBM(全局内存)加载到寄存器中,随后通过 Warp Scheduler 调用 Tensor Core 完成矩阵运算,最终再将运算结果回传至寄存器,以便进行后续的连续运算。然而,这一流程中存在两大显著问题。

首先,数据的搬运与计算过程紧密耦合,这导致线程在加载矩阵数据时不得不独立地获取矩阵地址,简而言之,Tensor Core 准备数据时,Warp 内线程分别加载矩阵数据 Data Tile,每一个线程都会获取独立矩阵块地址;为了隐藏数据加载的延时(全局内存到共享内存,共享内存到寄存器的数据加载),会构建多层级软流水(software pipeline),使用更多的寄存器及存储带宽。这一过程不仅消耗了大量的继承器资源,还极大地占用了存储带宽,进而影响了整体运算效率。

其次,这一模式的可扩展性受到了严重限制。由于多级缓存 Cache 的存储空间限制,单个 Warp 的矩阵计算规格有上限,这直接限制了矩阵计算的规模。在大数据、大模型日益盛行的今天,这种限制无疑成为了制约计算性能进一步提升的瓶颈。

而第 4 代 Tensor Core 的引入,正是为了解决这些问题。英伟达通过全新的设计和优化,它旨在实现数据搬运与计算的解耦,提升存储带宽的利用率,同时增强可扩展性,以应对日益复杂和庞大的计算任务。随着第 4 代 Tensor Core 的广泛应用,计算性迎来新的飞跃。

Tensor Memory Accelerator

在第 4 代 Tensor Core 中,一个显著的创新是引入了 Tensor Memory Accelerator(简称 TMA),这一功能被称为增量内存加速。这一技术的出现,极大地提升了数据处理效率,为高性能计算领域注入了新的活力。

Hopper FFMA

对比 A100 与 H100 的 SM 架构图,如上图所示,我们可以发现二者在结构上并没有太大的差异。然而,由于工艺制程的进步,H100 中的 CUDA Core 和 Tensor Core 的密度得以显著提升。更为重要的是,H100 中新增了 Tensor Memory Accelerator,这一硬件化的数据异步加载机制使得全局内存的数据能够更为高效地异步加载到共享内存,进而供寄存器进行读写操作。

传统的 Warp-Level 编程模式要求所有线程都参与数据搬运和计算过程,这不仅消耗了大量的资源,还限制了计算规模的可扩展性。而单线程 schedule 模型则打破了这一束缚,它允许 Tensor Core 在不需要所有线程参与的情况下进行运算。这种设计大大减少了线程间的同步和协调开销,提高了计算效率。此外,使用 TMA(Tensor Memory Access)之前,用户只需要一次性配置好首地址、偏移量等 Tensor 描述信息。这种一次性配置的方式简化了操作流程,减少了重复配置的开销,使得 Tensor Core 能够更加专注于计算任务本身。

在 A100 时代,虽然已经实现了软件层面的数据异步加载,但 TMA 的硬件化实现无疑将这一功能推向了新的高度。通过 TMA,数据搬运与计算之间的耦合度得以降低,从而提高了整体运算效率。

分布式共享内存和 warp group 编程模式

Hopper TBC

如上图所示,在 H100 之前的架构中,线程的控制相对有限,主要基于 Grid 和 Block 的划分,分别对应硬件 SM 和 Device,且局部数据只能通过 shared memory 限制在 SM 内部,不能跨 SM。然而,在 Hopper 架构中,情况发生了显著变化。通过在硬件层面引入交叉互联网络,数据得以在 4 个 SM 之间进行拓展和共享,GPC 内 SM 可以高效访问彼此的共享内存。这一创新使得 SM 之间能够实现高效的通信,从而打破了之前架构中 SM 间的数据隔阂。

此外,随着硬件架构的变革,软件编程模式也相应发生了调整。Warp group 编程模式的提出,以及与之相关的 Tensor Block Cluster 概念,都体现了软硬件协同优化的思想。这种编程模式能够更好地利用 Hopper 架构的特性,实现更高效的计算性能。

更直观的从软件层面去看一下,有什么区别呢?

Hopper TBC Block

如上图左边所示,没有进行分布式共享内存时每个 Thread Block 都对应一个 SM,每个 SM 内部拥有自己的共享内存。然而,SM 与 SM 之间无法进行直接的数据交互,这意味着它们之间的通信必须通过全局内存进行。这种通信方式不仅增加了数据传输的时延,还可能导致寄存器的过度使用,降低了计算效率。

而在 H100 架构中,如上图右边所示,通过引入 SM 的 Cluster 或 Block 的 Cluster,实现了硬件层面的分布式共享内存。这意味着 SM 与 SM 之间的数据可以直接进行互联,无需再通过全局内存进行中转。这种机制极大地减少了数据传输的时延,提高了数据交互的效率。同时,由于数据可以在 SM 之间直接共享,寄存器的使用也得到了更加合理的分配,减少了不必要的浪费。

Hopper 直接读取共享内存异步 Tensor Core

此外,通过 TMA 将 SM 组织成一个更大的计算和存储单元,从而实现了数据从全局内存(global memory)到共享内存(shared memory)的异步加载,以及数据到寄存器的计算和矩阵乘法的流水线处理,最后通过硬件实现了矩阵乘法的流水线。硬件实现的矩阵乘法流水线确保了计算过程的连续性和高效性,使得 GPU 能够更快地处理大规模矩阵运算。

第五代 Tensor Core(Blackwell)

为了更好地适应 AI 工作负载的需求,同时提高性能和降低资源消耗。在 Blackwell 架构中,支持了第五代 Tensor Core,继续扩展了对低精度计算范围支持。第五代 Tensor Core 中,能够处理最低至 FP4 精度,并着眼于使用非常低精度的格式进行推理。与上一代英伟达 Hopper 相比,有着第五代 Tensor Core 支持的 Blackwell 架构可为 GPT-MoE-1.8 T 等大模型提供 30 倍的加速。

此外,为了应对那些 FP4 精度不足以满足的工作负载,第五代 Tensor Core 还增加了对 FP6 精度的兼容。虽然 FP6 精度在计算性能上并不比 FP8 有显著提升,因为它在英伟达的张量核心中本质上仍然是以类似 FP8 的方式进行操作,但由于数据大小缩小了 25%,它在内存占用和带宽需求方面带来了显著的优势。

对于大型语言模型(LLM)的推理任务而言,内存容量依然是这些加速器所面临的主要限制。因此,在推理过程中降低内存使用量成为了一个亟待解决的问题。通过采用低精度格式如 FP4 和 FP6,可以在保持推理质量的同时,有效减少内存消耗,这对于提升 LLM 推理的效率和可行性至关重要。

此外,第五代 Tensor Core 还支持社区定义的微缩放格式 MX(Microscaling)Format ,它是一种精度调整技术,相比一般的 scalar format (比如 FP32, FP16),MX Format 的粒度更高,多个 scalar 构成一组数据(vector format),它允许模型在保持相对高精度的同时减少计算资源的消耗。

MX Format 的核心特点是其由两个主要部分组成:scale(X)和 element(P)。在这种格式中,k 个 element 共享一个相同的 scale。Element 的定义是基于 scalar format,如 FP32、FP16 等。这种设计允许在保持一定精度的同时,通过共享 scale 来减少存储需求和计算开销。此外,我们可以将 MX Format 视为一种不带 shift 的量化方法。量化是一种将连续或高精度数据转换为低精度表示的技术,通常用于减少模型大小和加速推理过程。MX Format 通过引入 block size k 来定义量化的粒度,即每个 block 中的 element 数量。

ze 通常设置为 32,这意味着每个 scale 会影响 32 个 element。MX Format 的优势在于它提供了比传统的 per-tensor 或 per-channel 量化更低的粒度,这有助于在保持计算效率的同时提高精度。然而,这种更细的量化粒度也会带来额外的存储开销。MX Format 的另一个特点是其数据位度的灵活性。例如,MXFP4 格式中,scale bits 为 8,block size 为 32,这意味着每个 scalar 平均占用 12 比特(8 bits for scale + 4 bits for element),这比传统的 FP4 格式提供了更多的信息。总之,MX Format 可以被看作是一种定制的数据表示方式,旨在为特定的硬件平台提供加速。

此外,Blackwell 架构,进一步支持了第二代 Transformer 引擎。第二代 Transformer 引擎与第五代 Tensor Core 技术与 TensorRT-LLM 和 NeMo 框架创新相结合,加速大语言模型 (LLM) 和专家混合模型 (MoE) 的推理和训练,可将性能和效率翻倍,同时为当前和新一代 MoE 模型保持高精度。

小结与思考

  • 英伟达 GPU 架构自 Volta 起引入 Tensor Core 后,历经五代演进,每代都通过技术创新如 TMA 和分布式共享内存,显著提升了 AI 计算的效率和性能。

  • 五代 Tensor Core 的演进反映了英伟达对深度学习硬件支持的不断加强,特别是对低精度计算和大规模矩阵运算的优化,为 AI 训练和推理提供了更高效的硬件基础。

  • Blackwell 架构的第五代 Tensor Core 通过支持 FP4 和 FP6 精度计算,以及引入第二代 Transformer 引擎,展现了英伟达面向未来 AI 工作负载需求的前瞻性设计,进一步推动了生成式 AI 和大型语言模型的发展。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值