发表时间: 2024-03 · arXiv:2403.08245
原文: https://arxiv.org/abs/2403.08245
作者: Shawn Tan, Yikang Shen, Rameswar Pandarpanda, Aaron Courville
机构: mila.quebec, http://ibm.com, http://iro.umontreal.ca
一句话结论 本文提出了一种名为ScatterMoE的稀疏专家混合模型高效实现方法,通过引入全新的底层原语融合分组与线性变换步骤,在保持数值精度的同时显著降低了显存占用并提升了模型的训练与推理吞吐量。
要解决什么问题 现有的稀疏专家混合(SMoE)模型在GPU上的高效实现面临严重的显存开销与架构扩展性卡点。以广泛应用于Megatron-LM模型的Megablocks为代表的现有实现,在计算前需要对输入执行分散到分组的复制操作,这在训练阶段为了保存反向传播所需的张量,会产生巨大的显存分配开销。同时,为了迎合GPU的底层计算特性,现有方法通常会将路由到各个专家的张量块强制填充到相同大小,这种不必要的填充进一步加剧了高带宽内存的浪费。此外,将SMoE转化为稀疏矩阵格式的做法虽然在多层感知机上高效,但其固化的中间表示形式极难扩展到注意力机制等其他类型的专家模块上。早期的TPU实现甚至要求在编译时定死张量容量,一旦专家负载不均,要么丢弃超出容量的令牌,要么对空闲专家进行无效填充,造成严重的算力浪费。
怎么做的 核心思路是通过融合分组与线性变换步骤,彻底避免对输入进行显式填充和冗余复制,从而绕开显存分配的卡点。标准SMoE的计算需要先根据令牌嵌入分配权重并选择头部专家、将分配给同专家的令牌分组并产生扇出、执行专家线性变换、将令牌分散回原时间步,最后进行加权求和,其输出定义为 $$\mathbf{Y}_t = \sum_{e \in \text{topk}(g(\mathbf{X}_t))} g_e(\mathbf{X}_t) \cdot f_e(\mathbf{X}_t)$$ 传统方法会在高带宽内存中实例化整个填充数组并按排序复制数据,而ScatterMoE仅根据专家对令牌排序并对索引进行填充,在加载到静态RAM时直接根据填充后的索引读取,避免了全局显存占用。关键设计是由Triton编写的新原语ParallelLinear,其底层依赖一个名为scatter2scatter的核函数,能在分散的向量上直接执行分组矩阵运算。该原语支持输入和输出在分组与分散状态之间的四种任意组合,其产生的中间表示是标准的PyTorch张量,极大地提升了扩展性。在反向传播计算梯度 $$\nabla \mathbf{X} = \nabla \mathbf{Y} \mathbf{W}^{\top}, \quad \nabla \mathbf{W} = \mathbf{X}^{\top} \nabla \mathbf{Y}$$ 时,ParallelLinear在嵌入未分组时对其进行分组以计算权重梯度,并通过复用数组来最小化显存使用,例如将输出梯度的数组直接用作后续计算的输出。在具体实现多层感知机时,ScatterMoE将两次线性变换配置为先从分散到分组、再从分组到分散,使得反向传播只需一次分组操作。而在扩展到多头注意力混合模块时,由于应用位置编码需要保持令牌的时间顺序,ParallelLinear可以直接执行从分散到分散的变换,无需像现有方法那样分配额外的数组来回倒腾数据。该注意力实现类似于分组查询注意力,每个专家拥有特定数量的键头,并从中选择对应比例的查询头,从而实现高效的注意力混合计算。
效果如何 实验在同一计算节点上的8张Nvidia A100 GPU上搭建了1.5B参数的Mixtral配置模型,训练数据设置为有效批量大小256、序列长度2048个令牌,并在单卡上进行了多层感知机和注意力模块的单元测试。对比基线包括代表基础实现的HuggingFace朴素版本、代表当前高效稀疏路线的Megablocks稀疏模式及其内存高效模式,以及一种高效的PyTorch实现。在整体训练吞吐量上,ScatterMoE比稀疏Megablocks基线高出38.1%。在多层感知机单元测试中,ScatterMoE的训练显存占用仅为Megablocks的66.2%,推理显存占用更是低至53.6%。在测试细粒度专家设置时,随着粒度的增加,ScatterMoE展现出比Megablocks更好的吞吐量扩展性,特别是在批处理推理中优势明显。在降低稀疏性的实验中,即使将选中的专家数量增加到30个,ScatterMoE的吞吐量依然优于Megablocks,且两者均高于等效参数的密集模型。在注意力混合模块的测试中,当每次激活8个专家时,其推理吞吐量比Megablocks高出24.0%,且性能差距随粒度增加而拉大。此外,在winogrande、hellaswag等十余个语言模型评估基准上,ScatterMoE与HuggingFace标准实现的数值精度完全一致,绝对误差可忽略不计。作者也承认了当前方法的局限性,目前尚未实现用于加速解码的专用内核,且在多节点环境下的并行化支持仍需进一步开发。
核心问题: 尽管稀疏专家混合(SMoE)模型在扩展Transformer方面越来越受欢迎,但其在GPU上的高效实现仍面临挑战。现有的实现方式存在一些局限性:
scatter-to-group的复制操作,这在训练中会因为存储用于反向传播的张量而产生显著的内存分配开销。研究目标与创新点: 本文提出了ScatterMoE,一种旨在克服上述局限性的SMoE实现。其核心目标是改善批处理推理、训练速度和内存占用。
图 1: 当前的SMoE多层感知机(MLP)实现需要在分组时复制嵌入(左图),而ScatterMoE则融合了分组和线性变换步骤(右图),从而减少了我们方法的内存占用。不同的颜色代表不同的专家,垂直的矩形框代表嵌入,其上方或下方标注了相关的时间步。
其他实现与依赖关系。ScatterMoE的核心部分是使用Triton【【索引18,Triton: an intermediate language and compiler for tiled neural network computations,2019,Proceedings of the 3rd ACM SIGPLAN International Workshop on Machine Learning and Programming Languages】】实现的,这是一种基于图块(tile-based)的GPU编程语言,在Python中编写,使其易于修改和扩展。本文的主要比较对象是Megablocks,它使用同样基于Triton的STK框架实现。Megablocks被广泛应用于Megatron-LM模型【【索引16,Megatron-lm: Training multi-billion parameter language models using model parallelism,2019,arXiv】;【索引12,Efficient large-scale language model training on gpu clusters using megatron-lm,2021,Proceedings of the International Conference for High Performance Computing, Networking, Storage and Analysis】;【索引9,Reducing activation recomputation in large transformer models,2023,Proceedings of Machine Learning and Systems】】,是训练SMoE的一种高效方法。另一个流行的SMoE实现库是CUTLASS【【索引8,Who says elephants can’t run: Bringing large scale moe models into cloud scale production,2022,arXiv】】,Megablocks也使用它作为其分组计算的选项。
SMoE的其他应用。除了多层感知机(MLP),研究人员也提出了SMoE版本的注意力模块【【索引19,Mixture of attention heads: Selecting attention heads per token,2022,arXiv】;【索引2,Switchhead: Accelerating transformers with ´ mixture-of-experts attention,2023,arXiv】】。这些注意力混合(MoA)实现已被用于扩展通用Transformer(Universal Transformers)【【索引3,Universal transformers,2018,arXiv】;【索引17,Sparse universal transformer,2023,arXiv】】,并应用于全模块化Transformer的持续学习【【索引15,Moduleformer: Learning modular large language models from uncurated data,2023,arXiv】】。高效地计算SMoE将为这些模型的训练和推理带来巨大好处。
在本文中,我们将遵循矩阵使用粗体(例如X)的符号约定。除非另有说明,为便于理解,第一个维度是批处理-时间维度(batch-time,即将批处理和时间维度展平)。此外,$X_i$表示X的第i行。
SMoE模块的构成与计算流程。SMoE模块由E个专家(experts)组成,这些专家通常是具有相似架构的子模块。输入中的T个令牌(tokens)中的每一个都通过一个路由模块进行路由,然后根据路由器的输出权重分配给k个专家,其中k ≤ E。然而,朴素的SMoE计算方法(即遍历所有令牌并评估相应专家的输出)速度太慢,无法充分利用GPU的并行计算能力。在实践中,SMoE的实现通常执行以下主要步骤:
$$\mathbf{Y}_t = \sum_{e \in \text{topk}(g(\mathbf{X}_t))} g_e(\mathbf{X}_t) \cdot f_e(\mathbf{X}_t)$$
最终产生N个嵌入。
专家模块的典型结构。通常,每个专家是一个多层感知机(MLP),带有一个维度为$d_{expert}$的隐藏层。
Megablocks与ScatterMoE的对比。在Megablocks中,步骤(1)和(4)会导致对原始输入的复制。它们进一步对每个专家的令牌块进行填充(padding),使其数量相等,以便于GPU计算(见图1)。这个过程会在高带宽内存(HBM)中为填充后的嵌入分配数组,并将原始嵌入按排序顺序复制进去。然后,对这个按专家排序的数组执行分组通用矩阵乘法(Grouped GeMM)。相比之下,ScatterMoE避免了在HBM中实例化整个填充数组。我们不是将所有嵌入复制到一个填充数组中,而是根据专家对令牌进行排序,并转而对索引进行填充。当将一个图块(tile)加载到静态RAM(SRAM)时,我们根据填充后的索引进行加载,从而得到一个填充后的图块。
ParallelLinear的核心功能。我们的SMoE实现依赖于ParallelLinear,它允许不同组合的分组通用矩阵乘法(Grouped GeMMs)。为了实现这一点,我们编写了一个名为scatter2scatter的Triton核函数,它支持图2中所示的所有操作组合。该操作融合了分组GeMM和分散的读写操作,使我们能够跳过一个中间的分组和复制步骤。ParallelLinear为输入和输出都提供了分组(grouped)和分散(scattered)的选项,从而产生了图2中看到的四种可能组合。通过这些操作的组合,我们可以实现ParallelLinear的前向和反向传播。
图 2: ParallelLinear允许执行不同组合的SMoE变换,使得输入和输出既可以是分组的也可以是分散的。这个基本功能构成了ScatterMoE前向和反向传播的基础。与现有实现不同,这些操作在执行时无需对输入和输出张量进行额外的复制(或填充)。
算法1:ParallelLinear前向传播。算法1提供了ParallelLinear的伪代码。它是scatter2scatter核函数的一个薄封装,分组选项作为参数提供给ParallelLinear。这是我们SMoE实现的主要工作引擎,可用于实现MLP和注意力层。我们独立于其下游用途实现了ParallelLinear的反向传播,使其可以作为构建其他专家的原语。
算法 1 ParallelLinear 前向传播
梯度计算。在一个典型的批处理线性变换$Y = XW$中,我们需要计算梯度$∇X$和$∇W$。
$$\nabla \mathbf{X} = \nabla \mathbf{Y} \mathbf{W}^{\top}, \quad \nabla \mathbf{W} = \mathbf{X}^{\top} \nabla \mathbf{Y},$$ParallelLinear中的梯度计算。在ParallelLinear中,我们将需要为E个专家中的每一个计算这些梯度。虽然这可以在$X$和$∇Y$都是分散的情况下计算,但当$X$和$∇Y$都是分组的时,该操作的实现速度最快。
算法 2 ParallelLinear 反向传播
内存优化策略。算法2在嵌入未分组时对其进行分组,以便计算$∇W$。groupXTY是实现这种分组矩阵乘法的核函数。虽然这种分组会为可能非常大的矩阵带来额外的内存分配,但这些数组分配可以被重用。一旦梯度$∇p$被计算出来,$Ŷ$的数组就可以用作$∇Ȳ$的输出。$X̄$可以被重用于$∇X̄$,因为它们的维度相同。然后,我们可以通过重用用于分组操作的数组来进一步最小化反向传播期间的内存使用。我们在算法2中分别用蓝色和橙色标记了被重用的数组。
内存占用优化。在SMoE MLP的背景下,我们可以进一步减少内存占用。MLP需要两次线性变换,可以天真地用两个设置为执行scatter-to-scatter变换的ParallelLinear操作来实现。然而,我们可以将这两个线性变换配置为scattered-to-grouped,然后是grouped-to-scattered。这将使得SMoE MLP中的每个ParallelLinear变换在反向传播期间只需要一次分组操作。
算法 3 SMOE 多层感知机
MoA的背景与挑战。已经有几种将SMoE应用于注意力层的提议【【索引19,Mixture of attention heads: Selecting attention heads per token,2022,arXiv】;【索引2,Switchhead: Accelerating transformers with ´ mixture-of-experts attention,2023,arXiv】;【索引17,Sparse universal transformer,2023,arXiv】】。无论采用何种形式,在应用注意力层之前,嵌入都应按时间顺序排列(即分散状态),以便应用位置嵌入并计算注意力权重和值嵌入的结果。使用现有的SMoE实现,这将需要额外的一对分组-分散操作,从而产生额外的内存成本。
算法 4 SMOE 多头注意力
ScatterMoE的优势。ScatterMoE提供了一个优势。由于我们可以通过ParallelLinear变换保持分散的顺序,因此我们可以实现MoA,而无需为分组和分散分配额外的数组。图3展示了用于SMoE注意力的操作。在本报告中,我们具体实现并基准测试了在【【索引17,Sparse universal transformer,2023,arXiv】】中发现的多头注意力混合(Mixture of Multi-head Attention)变体。
MoMHA的实现细节。这种实现类似于分组查询注意力(Grouped-query Attention, GQA)【【索引1,Gqa: Training generalized multi-query transformer models from multi-head checkpoints,2023,arXiv】】,其中每个键(key)头有多个可能的查询(query)头。而在SMoE设置中,将有$h_{expert}$个键头,并从可能的$E \cdot h_{expert}$个头中选择$k \cdot h_{expert}$个查询头,其中$h_{expert}$是每个专家的头数。
标准注意力实现约定。遵循标准的注意力实现约定,我们设置$d_{out} = d_{expert} \cdot d_{head}$,其中$d_{head}$是每个头的维度。然后在执行注意力操作时,我们相应地重塑张量,以使独立的头能够独立交互。
图 3: ParallelLinear允许从分散到分散的转换,从而保持了时间顺序。
算法4的说明。在算法4中,我们还考虑了时间维度,因此我们将输入和中间数组表示为具有批次、时间和嵌入维度($B \times T \times d$)的三维张量。在实践中,我们假设输入是连续的并且是按批次-时间排序的,这使我们能够展平张量并像在MLP的情况下一样继续进行。请注意,对于SMoE注意力,一个关键的区别是,我们要求ParallelLinear在第一次变换后给出未分组的输出,并且它在输出变换时接受未分组的输入,这意味着两个ParallelLinear变换都使用scattered-to-scattered配置(图2c)。
模型架构
硬件配置
软件配置
数据集与评估
winogrande, sciq, race, piqa, openbookqa, hellaswag, copa, boolq, arc_easy, arc_challenge(评估准确率)和wikitext(评估困惑度)。
图 4: (a) 1.5B模型训练吞吐量 (b) SMoE MLP单元吞吐量 (c) SMoE MLP单元内存使用
整体训练性能
SMoE MLP 单元基准测试
图 5: 在固定活跃参数和总参数的情况下,增加k和E。我们发现我们的实现随着k的增加扩展性更好。推理粒度扩展性能。如果我们只考虑前向传播,相对吞吐量的差异会更大。
粒度与吞吐量关系
图 6: 随着我们降低稀疏性(增加k)的相对吞吐量曲线
稀疏性降低的影响
图 8: MoMHA实现的粒度增加曲线。在这种情况下,由于专家之间共享键和值向量,活跃参数基线的吞吐量是变化的。
注意力混合(MoMHA)性能
Mixtral 推理结果一致性验证
表 1: 语言模型评估框架结果比较:Hugging Face 与 ScatterMoE 实现。两种实现之间的结果差异可以忽略不计。
结论: ScatterMoE是一种在Triton中实现的SMoE,与现有解决方案相比,它减少了内存占用并提供了稍高的GPU吞吐量。我们还设计了ScatterMoE以使用ParallelLinear原语,我们设想该模块可以被扩展,用于构建其他需要分组或分散线性变换的SMoE风格模块。目前,我们已经提供了基于ScatterMoE的MLP和Attention层的实现,希望这将有助于未来基于专家混合模型的实现,并作为将SMoE概念扩展到其他线性变换专家变体的实例。
局限性与未来工作: 目前,ScatterMoE没有实现用于加速解码的专门内核,并且在多节点环境中的并行化还需要进一步的工作。这些额外功能将在未来的迭代中添加,我们相信我们和开源社区的进一步测试将解决任何剩余的错误和未优化的性能问题。