专栏名称: 计算机视觉深度学习和自动驾驶
讨论计算机视觉、深度学习和自动驾驶的技术发展和挑战
目录
相关文章推荐
中科院物理所  ·  鱼儿性别紊乱,秃鹫肾衰竭,这个杀手还要制造多 ... ·  15 小时前  
中科院物理所  ·  当天上的垃圾越来越多 ·  2 天前  
中科院物理所  ·  这一家子个个是毒王,可还是没能逃离你的餐桌 ·  2 天前  
51好读  ›  专栏  ›  计算机视觉深度学习和自动驾驶

无干扰推理:混合下游工作负载的 分解LLM 推理

计算机视觉深度学习和自动驾驶  · 公众号  ·  · 2024-07-07 00:57

正文

24年1月来自中科院和华为云的论文“Inference without Interference: Disaggregate LLM Inference for Mixed Downstream Workloads”。

基于 Transformer 的大语言模型 (LLM) 推理服务现已成为许多云服务的骨干。LLM 推理包括预填充阶段和解码阶段。然而,现有的 LLM 部署实践往往忽视了这些阶段的不同特点,从而导致严重的干扰。为了减轻干扰,根据推理请求的特点仔细调度和分组推理请求。通过三大支柱,在 TetriInfer 中实现了这个想法。首先,它将提示分成固定大小块,加速器总是接近其计算饱和极限。其次,它分解预填充和解码实例,以便每个实例都可以独立运行。最后,它用一个智能两级调度算法并增强预测资源使用情况,避免解码调度热点。结果表明,TetriInfer 在性能/美元方面大幅提高了第一个token时间 (TTFT)、作业完成时间 (JCT) 和推理效率,例如,它使用的资源减少了 38%,同时平均 TTFT 和平均 JCT分别降低了 97% 和 47% 。


自 ChatGPT 以来,基于大语言模型 (LLM) 的服务已在日常生活中发挥着至关重要的作用。要运行推理请求,LLM 模型将首先获取用户输入以生成第一个 token(称为预填充阶段),然后以自回归方式逐个 token 生成输出(称为解码阶段)。

有多种方式可以与 LLM 交互,从简单的聊天到更复杂的下游任务,例如文档摘要、内容创建等。因此,支持 LLM 的服务可处理具有截然不同属性的推理请求,这些属性可分为两个维度:预填充阶段的输入提示长度和解码阶段的生成 token 长度。如图所示,摘要任务具有较长的输入提示和较短的生成tokens,而上下文创建任务则相反。不同下游任务的tokens长度可能相差两个数量级以上。

鉴于来自各种下游任务的 LLM 推理请求存在显著差异, 第一个研究的问题是,这些推理请求在一起运行时的表现如何? 为了回答这个问题,大量测试混合了不同长度的 LLM 预填充和解码请求。不幸的是,所有组合都存在严重干扰。例如,混合预填充请求可能导致速度减慢 10 倍,组合预填充和解码请求可能导致速度减慢 5 倍,而混合不同长度的解码请求可能会导致 16% 的吞吐量损失。避免干扰的一个简单解决方案是静态地为每个下游任务配置资源。

鉴于 LLM 服务基础设施的高成本,这种解决方案是不切实际的。为此, 第二个研究的问题是,如何构建一个最小化干扰的分布式 LLM 推理服务系统?

LLM 推理,是根据输入提示生成输出tokens序列的过程。此过程包含两个阶段:预填充和解码。预填充阶段输出第一个token并生成K-V缓存以供将来解码 [21]。解码阶段使用之前的 KV 缓存以自回归的方式逐步生成新tokens。通常,预填充阶段受计算限制,而解码阶段受内存限制 [33]。如图所示,实验结果表明,一旦加速器在一定数量的tokens上达到饱和(称为加速器饱和阈值),预填充阶段的吞吐量就会保持平稳。解码阶段的吞吐量会随着批次大小的增加而继续增加,但一旦内存带宽饱和就会达到稳定水平。

为什么存在干扰?根本问题在于,当前的 LLM 部署实践没有考虑到 LLM 预填充和解码阶段所表现出的不同特征。具体来说, 预填充阶段 类似于计算繁重的批处理作业,其计算量与输入提示长度成二次方关系。 解码阶段 类似于内存密集型、延迟-关键型任务,其资源使用量与生成的tokens长度成亚线性关系 [33]。


在测试中观察到的 干扰 ,是经典的系统问题。运行预填充请求,会导致严重的减速,因为这是在饱和的硬件继续添加计算繁重的作业。结合预填充和解码请求会对两者造成损害,因为系统在同时运行批处理和延迟关键型作业。混合解码请求会导致吞吐量下降,因为不知道内存带宽和容量使用情况,从而导致争用和队头(head-of-line)阻塞。

TetriInfer 是一个旨在对抗干扰的 LLM 推理服务系统。如图展示其工作流和架构图:(a) 比较现有系统和 TetriInfer 的执行时间线,现有系统有两个节点运行混合预填充和解码,TetriInfer 将预填充和解码实例分开,这允许在不同的按需解码实例之间对长解码任务进行负载平衡;每个时间线包含四轮(R1 到 R4),预填充和解码框的长度表示它们的序列长度,解码框的宽度表示其资源使用情况;更宽的解码框表示存在较长的生成tokens,从而导致更大的资源使用率和解码延迟;(b) 显示 TetriInfer 的架构,其中突出显示了四个核心模块:集中控制平面、预填充实例、解码实例和长度预测模型。

集中控制平面 。它由一个全局调度程序和一个集群监视器组成。全局调度程序根据负载将请求发送到预填充实例,并接收来自解码实例的流输出。集群监视器从预填充和解码实例收集统计信息,并定期将负载信息广播到预填充实例。它添加、删除和翻转预填充或解码实例。

预填充实例 。它们仅运行 LLM 推理请求的预填充阶段。每个预填充实例都有一个本地调度程序、一个长度预测器、主 LLM 引擎和一个调度程序。所有请求都经过四个步骤。1)本地预填充调度程序根据预定义的策略对请求进行排序。2)长度预测器运行预测模型来推测请求的解码长度,然后使用它们来估计解码阶段的资源使用情况。3)主 LLM 引擎将所有请求划分为固定块。4)对于每个请求,调度程序运行解码间负载平衡算法来选择一个解码实例,然后将生成的 KV 缓存转发给它。

解码实例 。它们实际上与预填充实例分离,并且仅运行 LLM 推理请求的解码阶段。每个解码实例都可以接收来自任何预填充实例的请求。它运行一个本地调度程序,该调度程序具有三个预定义策略,用于选择要在主 LLM 引擎中运行的解码请求。

长度预测模型 。预测模型是一个小型 LLM 模型,经过离线微调,用于预测 LLM 推理请求的生成长度。TetriInfer 的预填充调度程序和解码实例的本地调度程序利用推测的信息来调度解码实例并避免测量热点。预测模型很小,部署在所有预填充实例上。

预填充实例的调度程序对于改善预填充阶段的延迟和吞吐量至关重要。调度程序维护一个原始请求队列,该队列存储来自全局调度程序的请求,以及一个存储排序请求的调度队列。在这项工作中,实现了三种调度程序策略:先到先服务 (FCFS)、最短作业优先 (SJF) 和最长作业优先 (LJF)。

如图是预填充调度程序策略。左侧显示四个原始推理请求(R1 至 R4)。右侧显示使用 FCFS、SJF 和 LJF 的调度请求。这种分块版说明了切片和合并(C1 至 C4)。具体而言,FCFS 保持原始请求到达顺序。提示tokens按顺序划分并合并为块。此策略最容易实现,并且最适合具有相似提示长度的推理请求。但是,当请求具有较长的提示时,FCFS 可能导致队头阻塞和较高的平均作业完成时间 (JCT)。这是有问题的,因为 LLM 推理请求之间的长度差异超过三个数量级。

如图是预填充预测模型的微调和预测流程。目标模型是想要预测其解码行为的模型。预测模型是训练的模型,不涉及在线微调。在此过程中,训练预测模型(以红色表示)以推测特定目标模型(以蓝色表示)的解码行为。预测模型的微调涉及三个关键步骤。首先,组装一个从公共数据集继承的仅提示训练数据集、一个大型目标 LLM 模型(例如 OPT-13B)和一个用于预测模型的分类模型(例如 125M OPTForSequenceClassification [16])。其次,向目标 LLM 模型发送训练提示,该模型生成响应。随后,将生成的响应分类到具有选定粒度的固定大小存储桶中。例如,使用粒度 100,token长度在 0 到 200 之间的响应 tokens 分类为 0,在 200 到 400 之间的响应 tokens 分类为 1,依此类推。这些标签与训练提示配对以创建新的数据集。最后,将新数据集划分为训练部分和评估部分,然后继续使用该数据集训练和评估预测模型。

一旦主 LLM 完成其预填充阶段,预填充的 KV 缓存就会在加速器的内存(例如 GPU 的 HBM)中生成。目标是将此缓存传输到所选解码实例的加速器内存,不管系统部署在哪个硬件平台上。这很有挑战性,因为预填充和解码实例之间存在多个物理数据链路,每个链路都需要不同的软件堆栈。

将现有的物理数据链路分为三类,如图所示。第一种称为







请到「今天看啥」查看全文