接上回的算子层面优化内容,本节从系统层面介绍模型层面的优化内容。

模型优化与执行

对于本质上主要是数据并行的操作,通用 CPU 远远落后于 GPU 和其他极端并行处理器架构。 为了最大限度地利用这种能力,需要采用内核设计技术(第 3.1 节),该技术旨在开发优化的内核程序,以便在 GPU 上执行推理算子。 这些设备提供的极端计算能力也促成了请求批处理技术(第 3.2 节),该技术旨在充分发挥这种能力,同时优化诸如因不断增长的 KV 缓存而导致的内存过度分配等问题。 类似的激发了请求调度技术(第 3.3 节),包括作业优先级排序和负载平衡技术。 这些技术取决于准确预测请求在其生命周期内的总内存成本以及执行轮数的能力。 在缺乏准确预测的情况下,可以使用缓解策略来适应出现的新内存状况。 这些技术在第 3.4 节中进行了集体讨论。

3.1内核

物理算子的成本包括算子设计之外的各种因素,包括运行 I/O 成本(由在算子执行期间读取和写入中间产品引起)和调用成本(由在处理器内核中加载和卸载中间程序引起)。 对于大语言模型推理,由于注意力机制和FFN算子可能产生的大量矩阵乘积(激活),I/O成本变得尤为重要。 对于基于GPU的工作流程,由于可能需要单独启动多个内核才能完成单个算子,因此调用成本也可能变得非常重要。

内核融合kernel fusion将多个操作组合到一个内核中,从而同时避免了物理调用成本。 这种技术,结合分块矩阵乘法和在线Softmax online技术,激发了分块注意力内核的开发,与使用通用GPU内核相比,它可以提供巨大的加速,包括分布式注意力内核等,旨在通过多个GPU加速进行推理的新方法。 这些技术也启发了注意力机制之外的其他算子的内核,包括FFN的内核,以及非矩阵算子的内核的优化新思路。

Refer to caption

图7: 分块矩阵乘法的分配策略。

3.1.1注意力内核

Refer to caption

图8: 使用非融合(a)和融合(b)内核的注意力算子。 融合算子将分块矩阵乘法与在线softmax结合起来,以允许以分块方式编写U,而无需利用中间注意力模式。

方程式2中给出的注意力算子需要计算两个矩阵乘积以及softmax。 虽然在矩阵乘法期间发生的各个标量乘积和和是可交换的和结合的,从而允许简单的并行化,但是由于数据的不均衡性,天真地将标量运算分布在GPU的处理器内核(即SM单元)上会导致低利用率。 此外,获取中间矩阵乘积需要昂贵的I/O。 像FlashAttention这样的分块注意力内核将在线softmax online与分块矩阵乘法融合在一起,可以解决这两个问题。 同时,具有极长上下文的请求(注释7)可能需要跨多个GPU分发KV缓存。 分布式注意力核,例如 Ring Attention ,旨在处理这些情况,同时处理传输和同步成本。

分块注意力。 为了提高核心利用率,Stream-K 将矩阵乘积划分为缓存局部分片,并将每个分片中的标量积依次分配给处理器核心,如图 7© 所示。 这种流式机制被证明可以消除其他策略(如循环分配(图 7(a))或固定分割(图 7(b))分配)可能导致的空闲工作进程。 虽然这项技术可以直接用于注意力机制内部的矩阵乘积,但它仍然需要在应用 softmax 之前获取完整的 Q⁢K⊤ 中间乘积(图 8(a))。

现在有许多用于其他注意力变体的下游核,主要是稀疏注意力,它们主要采用这些技术。 例如,FlashMask 将融合注意力推广到支持注意力掩码. 给定任意掩码运算符,FlexAttention根据运算符编译一个新的融合注意力核。 与手工制作的内核(如 FlashAttention)相比,自动生成的内核提供了类似的速度提升。

Refer to caption

图 9: 环形注意力的简化示例,显示了分布式 Q⁢K⊤。 在每个时间步,工作进程 i 异步地将处理后的输入片传输到序列中的下一个工作进程。 最终,每个工作进程都会处理每个输入片,同时只需要足够的存储容量来一次保存几个分片。

分布式注意力。 Ring Attention考虑了注意力算子分布在多个设备上的情况,而不仅仅是并行化在单个设备的处理器核心上。 Q 矩阵按行平铺,因此每个worker设备获得与提示段对应的查询子集,然后 K 矩阵按列平铺并分发给worker。

为了写入注意力行,每个worker必须处理每个 K 矩阵分片,这需要一种交换机制来协调分片从一个worker到下一个worker的传输。 Ring Attention 采用了一种去中心化的机制,其中worker以确定的顺序传输分片,同时将通信与分片处理重叠,以减少有效开销。 图 9 说明了一个简化的示例。

3.1.2其他内核

对于 FFN,f1、f2 和 g 函数都可以按元素实现,从而可以将它们流水线化成单个融合内核。 此属性还允许它直接融合到分块注意力内核,从而略微降低延迟 。

对于其他算子,LightSeq 将连续的非 GeMM 运算组合成单个融合内核,从而为包括层归一化、张量重塑、softmax 和 ReLU 激活在内的运算生成多个手工内核。 与基于供应商内核的实现相比,结果是每个transformer块的内核调用次数减少了 4 倍。除了融合内核,DeepSpeed-Inference 还利用 CUDA Graphs以单次调用启动多个内核。

3.2批处理

Refer to caption

图 10: 批量注意力。 请求级的更新向量可以通过沿批次维度连接输入矩阵,或通过为每个请求使用单独的内核(a,展示了一个非融合内核),在单个注意力内核中计算出来(b)。

在计算注意力模式之前,输入嵌入会乘以WQ、WK和WV,以产生低维的查询向量、键向量和值向量。 这些向量可以通过计算单个矩阵乘积来生成,对于多个批处理请求,可以通过水平连接权重矩阵和垂直连接Token嵌入来生成。 结果向量可以同样地与KV缓存中的向量连接起来,以形成用于批量注意力的三维矩阵输入。 图10(a) 说明了这项技术。

如果批量注意力算子的输入是不规则的,换句话说,每个请求的查询矩阵和键矩阵的长度或宽度不相等,那么计算矩阵乘积可能会由于矩阵的稀疏性而导致处理器内核利用不足。 由于解码阶段请求的KV缓存大小不相等,以及预填充阶段请求的prompt长度不相等,这种情况经常发生。 另一方面,拆分批次可以避免稀疏矩阵,但需要单独启动内核,批次中的每个请求都需要启动一个内核 yu2022orca (图10(b))。

此外,批处理频率和大小会影响诸如内存超额订阅和因落后者导致的延迟等问题。 在静态批处理下,批次中的每个请求都会执行到完成,然后才会处理下一个批次,这会导致落后者延迟批次的可能性。 此外,由于解码轮数未知,静态批处理有可能会过度订阅内存容器,因为每次解码后内存使用量都会增加。 动态批处理可以用来减轻落后者造成的影响,而仔细控制批次大小可以用来避免过度订阅,尤其是在与作业优先级排序(第3.3节)和内存管理技术(第4节)结合使用时。

动态批处理。 通过静态批处理,批次中的请求会被一起执行和返回,因此它们的延迟看起来是相等的,即使某些请求可能早在其他请求之前就已经到达了终止状态。 为了避免掉队者延迟批处理完成,(1) 连续批处理在每次执行轮次后重构批次,而不是在完成时重构 。 这种简单的机制提供了对请求执行的更大控制。 例如,如果在执行轮次之后完成批次中的一个请求,则可以立即驱逐其 KV 缓存,从而为下一个排队的请求加入批次腾出空间。 (2) 分块预填充 通过将 prompt 分成小块,在多个执行轮次中进行处理,从而将连续批处理的思想扩展到预填充阶段 。

Refer to caption

图 11: 静态批处理 (a) 在批次中的所有请求都完成后重新制定活动批次,而连续批处理 (b) 在每次解码轮次后重新制定批次。 请注意,此图显示了按最短剩余时间优先排序的请求。

批次大小。 对于静态批处理,可以通过贪婪装箱法形成批次。 批次大小受可用内存的限制,因为所有解码轮次中,所有批处理请求的 KV 缓存和中间产品的最大总内存使用量必须能够容纳在内存容器内。

对于动态批处理,即使总内存最终将超过内存容器,也可以执行批处理,因为批处理在每一轮之后都会重新配置,因此可以通过批处理具有小 KV 缓存的许多请求来实现非常大的批次大小。 尽管如此,大型批次会增加由于缓存增长而导致抢占的风险,但另一方面,小型批次会降低吞吐量并可能导致资源未得到充分利用。 大多数推理系统通过将批次大小固定为通过离线测试发现的常数,例如 Orca,或者通过固定的 token 预算,来平衡这两种风险。

3.3调度

当请求速率超过系统吞吐量时,新请求必须在队列中等待才能被处理。 由于在队列中等待的时间会增加请求延迟,因此处理请求的顺序会通过缩短或延长等待时间来影响延迟。 这种性质的作业调度问题出现在许多领域,并且诸如先来先服务 (FCFS)、最短作业优先 (SJF) 和多级队列 (MLQ) 等经典技术可以很容易地应用于大语言模型推理 。

但是,由于 KV 缓存增长导致极端且不可预测的内存压力,大语言模型推理系统可能面临较高的抢占风险。 同时,抢占后的请求恢复可能会很昂贵,需要计算密集型的预填充阶段,或者需要从二级或远程存储进行带宽密集型传输,以便恢复丢失的缓存。 除了恢复机制(第 4.2 节)之外,这些因素还导致了旨在防止代价高昂的抢占的动态提升机制 。

此外,配备多个推理副本的系统(第 5.2 节)需要负载平衡机制来进行请求分配,例如通过贪婪的最小负载分配 。 为了弥补不准确的负载预测,可以使用动态重新平衡技术来迁移请求,以响应不断变化的工作节点条件 。 对于支持缓存共享的系统(第 4.4 节),缓存可用性也可用于指导负载平衡决策,因为最大化这些机会有助于减少总体负载。

Refer to caption图 12: 使用 FCFS (a)、SJF (b) 和 MLQ © 进行调度。

作业优先级排序。 请求优先级确定请求处理顺序,同时也影响与内存相关的抢占,因为优先级最低的请求通常是被抢占的请求。 请求抢占通过删除与被抢占请求相对应的缓存条目来减少内存压力。 但是,恢复时,需要恢复缓存条目,以及是否通过重新计算或从卸载的容器中检索来恢复缓存取决于缓存大小和其他因素。

(1) FCFS 下,队列中花费更多时间的请求被赋予更高的优先级,但是此策略可能会导致队头阻塞,因为早期的长时间运行的请求可能会延迟稍后运行的短时间运行的请求的执行,否则这些短时间运行的请求会很快完成。 (2) SJF 策略避免了这个问题并实现了最小的平均延迟,但是需要对解码轮数进行准确的预测。 我们将在第 3.4 节中共同讨论负载预测。 但此外,SJF 也存在任务饥饿的风险,因为具有高预测轮数的请求可能会由于具有低预测轮数的请求的到来而持续降级。 为了避免饥饿,可以物理限制请求。 另一方面,如果无法获得准确的任务完成时间,则可以使用 (3) MLQ 策略,通过逐步降低长时间运行的请求的优先级来模拟 SJF,而不是依赖于固定的优先级。 该技术应用于大语言模型推理,方法是根据 prompt 长度为新请求分配初始优先级,然后根据生成的输出 token 数量逐步降低每个活动请求的优先级。

除了这些经典的调度技术之外,计算 KV 向量的高成本促使 (4) 基于缓存的 策略应用于支持缓存共享的系统,这些策略优先考虑请求,以最大限度地提高缓存命中率,从而避免缓存抖动。

负载均衡。 当跨worker的最大负载(以总计算成本衡量)为最小时,可以实现最佳负载均衡。 当知道分配各种任务引起的负载时,将到达的任务贪婪地分配给负载最小的worker会产生一个最大负载,在最坏的情况下,该负载最多是最佳解决方案的两倍。贪婪负载均衡的合理性能促使其在多副本推理系统中得到采用,但也导致不可避免地需要负载预测。 使预测复杂化的是由于 KV 缓存随时间增长而导致的动态负载变化,以及由请求抢占、恢复和自然终止引起的内存波动。 由于负载预测对于调度以及负载均衡都很重要,因此我们在第 3.4 节中统一讨论这些技术。 除词以外,还可以分配请求以最大限度地提高缓存命中率,以便利用缓存共享 。

还可以定期重新平衡请求,以补偿不准确的负载预测。 解码阶段的请求会根据其 KV 缓存大小的变化进行重新平衡。 为了更好地描述worker负载,为worker设置了缓存大小限制,以便可以为具有高大小限制的worker分配少量长时间运行的请求,以避免与内存相关的抢占,而可以为具有低大小限制的worker分配大量短时间运行的请求,因为抢占的风险降低了。 最初,请求是基于前缀长度分配给worker的。 但是,随着解码轮次导致缓存大小的增长,带有超过特定大小阈值缓存的请求会被重新分配到更合适的工作节点。 请求通过基于负载形成工作者对定期重新平衡,然后将请求从该对中负载较高的工作者迁移到负载较低的工作者,直到两者之间的负载达到平衡。

3.4讨论

硬件加速器已被充分利用以开发高效内核来加速大语言模型推理,但负载预测仍然是一个紧迫的挑战。 相关的是动态批处理场景下的最优批量大小问题。 大型批次大小可以提高吞吐量,但也增加了内存相关抢占的风险,而较小的批次大小可能导致计算能力未充分利用。 现有系统倾向于建立一个 Token 预算,动态调整批次大小直至达到该预算。 但这种方法更多地旨在实现由动态批处理提供的平衡 TTFT 和 TBT,而较少关注吞吐量与计算能力的平衡。
考虑到负载预测的难度,我们注意到,针对特定应用的推理系统可以与前端以及执行运行时共同设计,以约束输出,使其长度能够以高精度得知。 我们在第5.2节中详细阐述了这一策略。

这些类型的负载预测可以直接用于SJF调度,但是为了将它们用于负载平衡,它们应该包括其他因素,这些因素考虑了worker上的负载波动。 例如,将请求内存使用预测与估计的内存回收率相结合,以便提供更积极的内存可用性度量。Mooncake 使用类似的方法,同时也考虑了由于KV缓存传输而损失的时间。

如何学习大模型 AI ?

由于新岗位的生产效率,要优于被取代岗位的生产效率,所以实际上整个社会的生产效率是提升的。

但是具体到个人,只能说是:

“最先掌握AI的人,将会比较晚掌握AI的人有竞争优势”。

这句话,放在计算机、互联网、移动互联网的开局时期,都是一样的道理。

我在一线互联网企业工作十余年里,指导过不少同行后辈。帮助很多人得到了学习和成长。

我意识到有很多经验和知识值得分享给大家,也可以通过我们的能力和经验解答大家在人工智能学习中的很多困惑,所以在工作繁忙的情况下还是坚持各种整理和分享。但苦于知识传播途径有限,很多互联网行业朋友无法获得正确的资料得到学习提升,故此将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

在这里插入图片描述

第一阶段(10天):初阶应用

该阶段让大家对大模型 AI有一个最前沿的认识,对大模型 AI 的理解超过 95% 的人,可以在相关讨论时发表高级、不跟风、又接地气的见解,别人只会和 AI 聊天,而你能调教 AI,并能用代码将大模型和业务衔接。

  • 大模型 AI 能干什么?
  • 大模型是怎样获得「智能」的?
  • 用好 AI 的核心心法
  • 大模型应用业务架构
  • 大模型应用技术架构
  • 代码示例:向 GPT-3.5 灌入新知识
  • 提示工程的意义和核心思想
  • Prompt 典型构成
  • 指令调优方法论
  • 思维链和思维树
  • Prompt 攻击和防范

第二阶段(30天):高阶应用

该阶段我们正式进入大模型 AI 进阶实战学习,学会构造私有知识库,扩展 AI 的能力。快速开发一个完整的基于 agent 对话机器人。掌握功能最强的大模型开发框架,抓住最新的技术进展,适合 Python 和 JavaScript 程序员。

  • 为什么要做 RAG
  • 搭建一个简单的 ChatPDF
  • 检索的基础概念
  • 什么是向量表示(Embeddings)
  • 向量数据库与向量检索
  • 基于向量检索的 RAG
  • 搭建 RAG 系统的扩展知识
  • 混合检索与 RAG-Fusion 简介
  • 向量模型本地部署

第三阶段(30天):模型训练

恭喜你,如果学到这里,你基本可以找到一份大模型 AI相关的工作,自己也能训练 GPT 了!通过微调,训练自己的垂直大模型,能独立训练开源多模态大模型,掌握更多技术方案。

到此为止,大概2个月的时间。你已经成为了一名“AI小子”。那么你还想往下探索吗?

  • 为什么要做 RAG
  • 什么是模型
  • 什么是模型训练
  • 求解器 & 损失函数简介
  • 小实验2:手写一个简单的神经网络并训练它
  • 什么是训练/预训练/微调/轻量化微调
  • Transformer结构简介
  • 轻量化微调
  • 实验数据集的构建

第四阶段(20天):商业闭环

对全球大模型从性能、吞吐量、成本等方面有一定的认知,可以在云端和本地等多种环境下部署大模型,找到适合自己的项目/创业方向,做一名被 AI 武装的产品经理。

  • 硬件选型
  • 带你了解全球大模型
  • 使用国产大模型服务
  • 搭建 OpenAI 代理
  • 热身:基于阿里云 PAI 部署 Stable Diffusion
  • 在本地计算机运行大模型
  • 大模型的私有化部署
  • 基于 vLLM 部署大模型
  • 案例:如何优雅地在阿里云私有部署开源大模型
  • 部署一套开源 LLM 项目
  • 内容安全
  • 互联网信息服务算法备案

学习是一个过程,只要学习就会有挑战。天道酬勤,你越努力,就会成为越优秀的自己。

如果你能在15天内完成所有的任务,那你堪称天才。然而,如果你能完成 60-70% 的内容,你就已经开始具备成为一名大模型 AI 的正确特征了。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

在这里插入图片描述

更多推荐