本章节首先从AI芯片分类到发展趋势进行介绍,然后对于AI技术的种类、优化方向及关键指标进行介绍,为软件硬化打下一个概念基础。本文主要参考《ZOMI酱:AI系统》:
https://chenzomi12.github.io/02Hardware01Foundation/README.html
AI计算中可以用到的四种芯片类型:
按照应用场景的角度,AI 芯片可以分为云端,边缘端两类。
整体上边缘计算基本上就是推理用的,而推理比训练需要的算力比较小,其实也可以一块芯片通用,例如推理使用一个,那训练就使用多个使用PCI-E等连接起来,就提高了算力。
推荐一篇2018年图灵奖的文章:“计算机架构的新黄金时代:特定领域的硬件/软件协同设计、增强的安全性、开放指令集和敏捷芯片开发”,涵盖了计算机架构的最新发展和未来方向。:https://cacm.acm.org/research/a-new-golden-age-for-computer-architecture/ ,这篇文章出来的时候,2022年底的TensorFlow还没有爆发,其在计算机架构未来机遇章节提到了很多AI相关:
领域特定架构。 一种更以硬件为中心的方法是设计针对特定问题领域量身定制的架构,并为该领域提供显著的性能(和效率)提升,因此得名“领域特定架构”(DSA)。DSA 是一类专为特定领域量身定制的处理器——可编程且通常图灵完备,但针对特定类型的应用量身定制。从这个意义上讲,它们不同于专用集成电路 (ASIC),后者通常用于单一功能,代码很少更改。DSA 通常被称为加速器,因为与在通用 CPU 上执行整个应用程序相比,它们可以加速部分应用程序。此外,DSA 可以获得更好的性能,因为它们更贴合应用程序的需求;DSA 的示例包括图形处理单元 (GPU)、用于深度学习的神经网络处理器以及用于软件定义网络 (SDN) 的处理器。DSA 能够实现更高的性能和更高的能效,主要有以下四个原因:
首先,也是最重要的一点,DSA 针对特定领域采用了更高效的并行形式。例如,单指令多数据并行 (SIMD) 比多指令多数据并行 (MIMD) 更高效,因为它只需获取一个指令流,并且处理单元同步运行。9尽管SIMD 不如 MIMD 灵活,但它与许多 DSA 非常匹配。DSA 还可以使用 VLIW 方法实现 ILP,而不是推测性乱序机制。如前所述,VLIW 处理器不太适合通用代码15,但对于有限的领域来说,VLIW 效率更高,因为其控制机制更简单。具体而言,大多数高端通用处理器都是乱序超标量处理器,需要复杂的控制逻辑来执行指令启动和指令完成。相比之下,VLIW 在编译时执行必要的分析和调度,这对于显式并行程序非常有效。
其次,DSA 可以更有效地利用内存层次结构。正如 Horowitz 所指出的,内存访问的成本比算术计算高得多。16例如,访问 32 KB 缓存中的块所需的能量成本大约比 32 位整数加法高 200 倍。这种巨大的差异使得优化内存访问对于实现高能效至关重要。通用处理器运行的代码中的内存访问通常表现出空间和时间局部性,但在编译时则不太可预测。因此,CPU 使用多级缓存来增加带宽并隐藏相对较慢的片外 DRAM 中的延迟。这些多级缓存通常消耗处理器大约一半的能量,但避免了几乎所有对片外 DRAM 的访问,因为这些访问需要的能量大约是最后一级缓存访问的 10 倍。
缓存有两个明显的缺点:
当数据集非常大时。 当数据集非常大且时间或空间局部性较低时,缓存根本无法正常工作;
当缓存运行良好时。 当缓存运行良好时,局部性非常高,这意味着,根据定义,大多数缓存在大多数时间处于空闲状态。
在内存访问模式定义明确且可在编译时发现的应用中(典型的 DSL 就是这样),程序员和编译器可以比动态分配的缓存更好地优化内存的使用。因此,DSA 通常使用由软件明确控制移动的内存层次结构,类似于矢量处理器的运行方式。对于合适的应用,用户控制的内存比缓存的能耗要低得多。
第三,DSA 在精度足够的情况下可以使用较低的精度。通用 CPU 通常支持 32 位和 64 位整数和浮点 (FP) 数据。对于机器学习和图形领域的许多应用来说,这种精度已经超出了实际需求。例如,在深度神经网络 (DNN) 中,推理通常使用 4 位、8 位或 16 位整数,从而同时提高数据和计算吞吐量。同样,对于 DNN 训练应用来说,FP 也很有用,但 32 位就足够了,16 位通常也能满足需求。
最后,DSA 受益于针对用领域特定语言 (DSL) 编写的程序,这些程序具有更多的并行性,改进了内存访问的结构和表示,并且更容易将应用程序有效地映射到领域特定处理器。
首先一个问题:AI计算都在做哪些运算?
下图是一个经典的图像分类的卷积神经网络结构,网络结构从左到右有多个网络模型层数组成,每一层都用来提取更高维的目标特征(这些中间层的输出称为特征图,特征图数据是可以通过可视化工具展示出来的,用来观察每一层的神经元都在做些什么工作),最后通过一个 softmax 激活函数达到分类输出映射。
接下来我们来了解一下神经网络中的主要计算范式:权重求和。下图是一个简单的神经网络结构,左边中间灰色的圈圈表示一个简单的神经元,每个神经元里有求和和激活两个操作,求和就是指乘加或者矩阵相乘,激活函数则是决定这些神经元是否对输出有用,Tanh、ReLU、Sigmoid 和 Linear 都是常见的激活函数。神经网络中 90%的计算量都是在做乘加(multiply and accumulate, MAC)的操作,也称为权重求和。
结合上面介绍的经典 AI 模型结构特点,AI 芯片设计可以引出如下对于 AI 计算模式的思考:
所以AI芯片还是ASIC:根据产品需求进行特定设计和制造的集成电路,能够在特定功能上进行强化,具有更高的处理速度和更低的功耗。
芯片制程,内存大小,核心数,带宽,算力等,这些指标体现了 AI 产品的核心竞争力。 一些基本概念介绍如下:
价格是市场选择 AI 产品时的重要考量指标,主要包括下面两部分:
硬件自身价格:这是指 AI 芯片本身的制造成本,包括芯片设计、制造、封装、测试等环节的费用。硬件自身价格直接影响到芯片的成本效益比,对于消费市场和大规模部署的场景尤为重要。较低的硬件价格可以降低设备制造成本,提高产品的竞争力。
系统集成上下游全栈等成本:除了硬件本身的成本外,还需要考虑与 AI 芯片相关的系统集成和全栈生态系统的成本。这包括软件开发、算法优化、系统集成、测试验证、软件支持等方面的成本。在实际应用中,AI 芯片往往需要与其他硬件设备、软件系统以及云端服务进行集成,这些集成成本也需要被考虑进来。
易用性 Flexibility: 一个好的 AI 芯片产品应该提供完善的软硬件支持、丰富的文档和教程、灵活的编程语言和框架支持,以及便捷的硬件接口和集成支持,从而满足开发者在不同应用场景下的需求,提高开发效率和用户体验。AI 芯片的易用性的具体理解为:
AI 芯片设计的关键点围绕着如何提高吞吐量和降低时延,以及低时延和 Batch Size 之间权衡。具体的实现策略主要表现在 MACs 和 PE 两个方向。
MACs就是乘加计算的优化:
PE就是处理单元(Processing Element),优化:
模型量化是指通过减少神经模型权重表示或者激活所需的比特数来将高精度模型转换为低精度模型。网络剪枝则是研究模型权重中的冗余,尝试在不影响或者少影响模型推理精度的条件下删除/修剪冗余和非关键的权重。量化压缩 vs 网络剪枝的示意如上图所示。
将高比特模型进行低比特量化具有如下几个好处。
定义时候神经网络使用的数据存储格式挺重要,主要有上面FP32, TF32, FP16, BF16 这四种类型。
据剪枝的时机和方式,可以将模型剪枝分为以下几种类型:
对神经网络模型的剪枝可以描述为如下三个步骤:
结合上面 AI 模型的量化和剪枝算法的研究进展,AI 芯片设计可以引出如下对于 AI 计算模式的思考:
随着神经网络应用的普及,越来越多的模型需要在特定的硬件平台部署,如移动端和嵌入式设备,这些平台普遍存在内存资源少,处理器性能不高,功耗受限等特点,所以慢慢演变出了一种轻量化的网络模型设计方向,即在保持模型精度基础上进一步减少模型参数量和计算量的网络模型结构。
网络模型的轻量级衡量指标有两个,一个是网络参数量、另一个是浮点运算数(Floating-point Operations, FLOPs),也就是计算量。
减少参数的一些方法:
根据模型在设备之间的通信程度,数据并行技术可以分为 DP, DDP, FSDP 三种。
数据并行是最简单的一种分布式并行技术,具体实施是将大规模数据集分割成多个小批量,每个批量被发送到不同的计算设备(如 NPU)上并行处理。每个计算设备拥有完整的模型副本,并单独计算梯度,然后通过 all_reduce 通信机制在计算设备上更新模型参数,以保持模型的一致性。
DDP 是一种分布式训练方法,它允许模型在多个计算节点上进行并行训练,每个节点都有自己的本地模型副本和本地数据。DDP 通常用于大规模的数据并行任务,其中模型参数在所有节点之间同步,但每个节点独立处理不同的数据批次。
在 DDP 中,每个节点上的模型副本执行前向和后向传播计算,并计算梯度。然后,这些梯度在不同的节点之间进行通信和平均,以便所有节点都可以使用全局梯度来更新其本地模型参数。这种方法的优点是可以扩展到大量的节点,并且可以显著减少每个节点的内存需求,因为每个节点只需要存储整个模型的一个副本。
DDP 通常与 AI 框架(如 PyTorch)一起使用,这些框架提供了对 DDP 的内置支持。例如,在 PyTorch 中,torch.nn.parallel.DistributedDataParallel
模块提供了 DDP 实现,它可以自动处理模型和梯度的同步,以及分布式训练的通信。
Fully Sharded Data Parallelism (FSDP) 技术是 DP 和 DDP 技术的结合版本,可以实现更高效的模型训练和更好的横向扩展性。这种技术的核心思想是将神经网络的权重参数以及梯度信息进行分片(shard),并将这些分片分配到不同的设备或者计算节点上进行并行处理。FSDP 分享所有的模型参数,梯度,和优化状态。所以在计算的相应节点需要进行参数、梯度和优化状态数据的同步通信操作。
如上图是 FSDP 并行技术的示意图,可以看到不同的计算节点多了一些虚线链接的通信操作。
将模型的张量操作分解成多个子张量操作,并且在不同的设备上并行执行这些操作。这样做的好处是可以将大模型的计算负载分布到多个设备上,从而提高模型的计算效率和训练速度。在张量并行中,需要考虑如何划分模型的不同层,并且设计合适的通信机制来在不同设备之间交换数据和同步参数。通常会使用诸如 All-reduce 等通信原语来实现梯度的聚合和参数的同步。
如下图是一个矩阵乘算子的张量并行示意。X 作为激活输入,A 作为算子权重,将 A 按列切分。每个计算节点保留一份完整的 A 和部分 A,最后通过 All Gather 通信将两个计算节点的数据进行同步拼接为一份完整的 Y 输出,供下一层使用。
将模型的不同层划分成多个阶段,并且每个阶段在不同的设备上并行执行。每个设备负责计算模型的一部分,并将计算结果传递给下一个设备,形成一个计算流水线。在流水并行中,需要设计合适的数据流和通信机制来在不同设备之间传递数据和同步计算结果。通常会使用缓冲区和流水线控制器来管理数据流,并确保计算的正确性和一致性。
如下图是一个流水线并行示意过程。假设一个模型有 Forward,Backward 两个阶段,有 0-3 共 4 层网络设计,分布在 4 个计算设备处理,右图展示了在时间维度下,不同层不同阶段的执行顺序示意。为了减少每个设备等待的时间(即中间空白的区域,称为 Bubble),一个简单的优化设计就是增加 data parallelism,让每层数据切分为若干个 batch,来提高流水线并行设备利用率。
AI 模型中往往包含大量的矩阵乘运算,该算子的计算过程表现为较高的内存搬移和计算密度需求,所以矩阵乘的效率是 AI 芯片设计是性能评估的主要参考依据。
芯片里的内存空间往往是有限的(成本高),表现为越靠近计算单元,带宽越快,内存越小。为了平衡计算和内存加载的时间,让算力利用率最大化,AI 芯片往往会进行由远到近,多级内存层级的设计方式,达到数据复用和空间换时间的效果。根据这样的设计,矩阵乘实际的数据加载和计算过程将进行分块 Tiling 处理。
矩阵乘作为 AI 模型中的重要性能算子,CPU 和 GPU 的平台上都有专门对其进行优化实现的库函数。比如 CPU 的 OpenBLAS, Intel MKL 等,GPU 的 cuBLAS, cuDNN 等。实现的方法主要有 Loop 循环优化 (Loop Tiling)和多级缓存 (Memory Hierarchy)。
矩阵乘作为计算机科学领域的一个重要基础操作,有许多优化算法可以提高其效率。下面我们对常见的矩阵乘法优化算法做一个整体的归类总结。
这些优化算法通常根据硬件平台、数据规模和计算需求选择不同的策略,以提高矩阵乘法运算的效率。在具体的 AI 芯片或其它专用芯片里面,对矩阵乘的优化实现主要就是减少指令开销,可以表现为两个方面: