【NLP】DeepSpeed-FastGen:通过 MII 和 DeepSpeed-Inference 为LLM生成高通量文本

【NLP】DeepSpeed-FastGen:通过 MII 和 DeepSpeed-Inference 为LLM生成高通量文本_第1张图片

一、简介

GPT-4 和 LLaMA 等大型语言模型 (LLM) 已成为服务于各个级别的人工智能应用程序的主要工作负载。从一般聊天模型到文档摘要,从自动驾驶到软件堆栈每一层的副驾驶,大规模部署和服务这些模型的需求猛增。虽然 DeepSpeed、PyTorch 等框架可以在 LLM 训练期间定期实现良好的硬件利用率,但这些应用程序的交互性和开放式文本生成等任务的较差算术强度已成为现有系统中推理吞吐量的瓶颈。

为此,由 PagedAttention 提供支持的vLLM等框架和Orca等研究系统显着提高了 LLM 的推理性能。然而,这些系统仍然难以提供一致的服务质量,特别是对于提示较长的工作负载。随着越来越多的模型(如MPT-StoryWriter)和系统(如DeepSpeed Ulysses)支持扩展到数万个令牌的上下文窗口,这些长提示工作负载变得越来越重要。为了更好地理解问题空间,我们提供了详细的示例,说明法学硕士文本生成如何在两个不同的阶段(称为提示处理和生成)工作。当系统将它们视为不同的阶段时,生成将被即时处理抢占,这可能会破坏服务级别协议(SLA)。

今天,我们很高兴推出 DeepSpeed-FastGen,该系统通过利用所提出的动态 SplitFuse 技术克服了这些限制,与 vLLM 等最先进的系统相比,有效吞吐量提高了 2.3 倍。DeepSpeed-FastGen 利用 DeepSpeed-MII 和 DeepSpeed-Inference 的组合来提供易于使用的服务系统。

快速入门:尝试 DeepSpeed-FastGen 就像安装最新的DeepSpeed-MII版本一样简单:

pip install deepspeed-mii

要使用简单的非持久管道部署生成文本,请运行以下代码。欲了解更多详情,请参阅第 5 节。

from mii import pipeline
pipe = pipeline("mistralai/Mistral-7B-v0.1")
output = pipe(["Hello, my name is", "DeepSpeed is"], max_new_tokens=128)
print(output)

二、现有的文学硕士服务技术

单个序列的文本生成工作负载由两个阶段组成:1) 提示处理,其中用户提供的文本被作为一批标记进行有效处理,以构建用于注意的键值 (KV) 缓存,2) 标记生成,它将向该缓存添加一个令牌并生成一个新令牌。在生成文本序列的过程中,模型将对模型进行多次前向调用以生成完整的文本序列。文献中提出了两种主要技术,并将其部署在系统中,以解决这些阶段可能出现的各种限制和瓶颈。

阻塞的KV缓存:

vLLM 发现大型单片 KV 缓存导致的内存碎片显着降低了 LLM 服务系统的并发性,并提出了分页注意力机制来启用非连续缓存并提高系统总吞吐量。KV 缓存中的底层存储不是分配单个可变大小的连续内存块,而是固定大小的块(也称为页面)。阻塞的 KV 缓存通过消除 KV 缓存引起的内存碎片来增加潜在序列并发量,从而提高系统吞吐量。HuggingFace TGI和NVIDIA TensorRT-LLM中还包含非连续 KV 缓存实现。

连续配料:

过去,动态批处理(即服务器等待多个请求同步处理)用于提高 GPU 利用率。然而,这种方法有缺点,因为它通常需要将输入填充到相同的长度或停止系统以等待构建更大的批次。

大语言模型 (LLM) 推理和服务的最新进展一直专注于细粒度调度和优化内存效率。例如,Orca 提出了迭代级调度(也称为连续批处理),它在模型的每次前向传递时做出不同的调度决策。这允许请求根据需要加入/离开批次,消除了填充请求的需要,从而提高了整体吞吐量。除了 Orca 之外,连续批处理还已在 NVIDIA TRT-LLM、HuggingFace TGI 和 vLLM 中实现。

在当前系统中,有两种主要方法来实现连续批处理。在TGI和vLLM中,生成阶段被抢占以在继续生成之前执行提示处理(在TGI中称为填充)。在 Orca 中,这些阶段是不区分的;相反,只要序列总数未达到固定范围,Orca 就会在正在运行的批次中添加提示。这两种方法都不同程度地需要停止生成来处理长提示。

为了解决这些缺点,我们提出了一种新颖的提示和生成组合策略,Dynamic SplitFuse。

三、Dynamic SplitFuse:一种新颖的提示和生成合成策略 

DeepSpeed-FastGen 旨在利用连续批处理和非连续 KV 缓存来提高数据中心 LLM 服务的占用率和响应度,类似于 TRT-LLM、TGI 和 vLLM 等现有框架。为了达到新的性能水平,DeepSpeed-FastGen 引入了 SplitFuse,它利用动态提示和生成分解和统一来进一步提高连续批处理和系统吞吐量。

1.三个性能洞察

在描述 Dynamic SplitFuse 之前,我们先回答三个关键性能问题,这些问题共同推动了其设计。

1. 哪些因素影响单个LLM的前进通过?为了有效地进行调度,有必要了解调度循环应控制哪些相关自变量。我们在下面观察到,与前向传递中的原始令牌数量相比,前向传递中的序列组成(序列中的批量大小)对性能的影响可以忽略不计。这意味着可以围绕单个信号(前向传递中的令牌数量)构建有效的调度程序。【NLP】DeepSpeed-FastGen:通过 MII 和 DeepSpeed-Inference 为LLM生成高通量文本_第2张图片

2. 模型的吞吐量如何响应前向传递中令牌数量的变化?LLM有两个关键的操作区域,并且过渡相对陡峭。对于少量令牌,GPU 瓶颈是从内存读取模型,因此吞吐量随令牌数量而变化,而对于许多令牌,模型的吞吐量受计算限制,并且吞吐量接近恒定。如果所有前向传递都位于吞吐量饱和区域,则模型应该高效运行。【NLP】DeepSpeed-FastGen:通过 MII 和 DeepSpeed-Inference 为LLM生成高通量文本_第3张图片

3. 应如何在多个前向传递中调度代币池?我们在上面观察到,对于对齐良好的输入,令牌吞吐量曲线是凹的,这意味着二阶导数必然小于或等于 0。例如,令 f(x) 是给定模型的延迟与吞吐量的凹函数。对于凹函数 f(x) ,以下成立:

【NLP】DeepSpeed-FastGen:通过 MII 和 DeepSpeed-Inference 为LLM生成高通量文本_第4张图片

这表明,对于要处理的给定令牌池2x,最大化吞吐量的方式是将它们均匀地分配到两个批次之间。更一般地,在必须通过 F 次前向传递消耗和处理 P 个代币的系统中,理想的分区方案将平均分配它们。

2.动态 SplitFuse

Dynamic SplitFuse 是一种新颖的令牌组合策略,用于快速处理和令牌生成。DeepSpeed-FastGen 利用动态 SplitFuse 通过从提示中获取部分令牌并将其与生成组合的功能,以一致的前向大小运行。特别是,Dynamic SplitFuse 执行两个关键行为:

  1. 长提示被分解为更小的块,并在多个前向传递(迭代)中进行调度,只有最后一次执行任何生成。
  2. 将编写简短的提示以准确填充目标代币预算。即使是简短的提示也可以被分解,以确保预算得到精确满足并且远期规模得到很好的调整。

这两种技术共同为所有用户指标提供了具体的好处:

  1. 更好的响应能力由于长提示不再需要极长的前向传递来处理,因此该模型将提供更低的客户端延迟。在同一时间窗口内执行更多的前向传球。
  2. 更高的效率:短提示与更大的代币预算的融合使模型能够在高吞吐量状态下持续运行。
  3. 更低的方差和更好的一致性:由于前向传递具有一致的大小,并且前向传递大小是性能的主要决定因素,因此每个前向传递的延迟比竞争系统更加一致,感知的生成频率也是如此。与其他先前的工作一样,没有抢占或长时间运行的提示来增加延迟。

因此,DeepSpeed-FastGen 将以允许快速持续生成的速率消耗来自传入提示的令牌,同时向系统添加令牌以提高系统利用率,与其他状态相比,为所有客户端提供更低的延迟和更高的吞吐量流生成。 -艺术服务系统。【NLP】DeepSpeed-FastGen:通过 MII 和 DeepSpeed-Inference 为LLM生成高通量文本_第5张图片

图 1:连续配料策略说明。每个块都显示前向传递的执行情况。箭头表示前向传递具有生成一个或多个标记的序列。vLLM 在前向传递中执行令牌生成或提示处理;令牌生成优先于提示处理。Orca 会在生成时完整运行提示。动态 SplitFuse 执行由生成令牌和提示令牌组成的固定大小批次的动态组合。

四、绩效评估

DeepSpeed-FastGen 利用其阻塞 KV 缓存和动态 SplitFuse 连续批处理提供最先进的 LLM 服务性能。我们按照下面讨论的基准测试方法,在一系列模型和硬件配置上针对 vLLM 评估 DeepSpeed-FastGen。

1.基准测试方法

我们使用两种主要的定量方案来衡量绩效。

吞吐量-延迟曲线:生产准备情况的两个关键指标是吞吐量(以每秒请求数衡量)和延迟(每个请求的响应能力)。为了衡量这一点,我们同时实例化多个客户端(范围从 1 到 32 个)并向服务器发送请求(总共 512 个)。每个请求产生的延迟是在端点测量的,吞吐量是通过完成实验的端到端时间来测量的。

有效吞吐量:交互式应用程序(例如聊天应用程序)可能具有比端到端延迟等顶级指标所能捕获的更严格和复杂的要求。我们特别关注日益流行的聊天用户场景:

  1. 用户通过发送提示来启动任务。
  2. 系统处理提示并返回第一个令牌。
  3. 后续令牌在生成时会流式传输给用户。

在此过程中的每个点,系统都有可能提供不良的用户体验;例如,如果第一个令牌到达太慢或者生成似乎停止了一段时间。我们提出了一个考虑这两个维度的 SLA 框架。

由于提示和生成文本的长度差异很大,影响计算成本,因此为吞吐量和延迟设置严格的 SLA 值是不切实际的。因此,我们将提示延迟的 SLA 定义为|提示中的令牌| / 512 秒(= 512 个令牌/秒)。此外,考虑到人类的阅读速度,我们将指数移动平均线 (EMA) 生成延迟的 SLA 设置为 2、4 或 6 个令牌/秒。遵守这些 SLA 的请求被视为成功,这些成功请求的吞吐量称为有效吞吐量

我们在 NVIDIA A100、H100 和 A6000 上的 Llama-2 7B、Llama-2 13B 和 Llama-2 70B 上评估 vLLM 和 DeepSpeed-FastGen。

2.吞吐量-延迟分析

在此实验中,DeepSpeed-FastGen 在吞吐量和延迟方面均优于 vLLM,提供具有更大吞吐量的同等延迟,或者在相同吞吐量的情况下提供更快响应的延迟。在配备 4 个 A100x80GB 的 Llama-2 70B 上,DeepSpeed-FastGen 在相同延迟(9 秒)下表现出高达 2 倍的吞吐量提升(1.36 rps 与 0.67 rps),或延迟降低高达 50%(7 秒与 14 秒),同时实现相同的吞吐量 (1.2 rps),如图 2 所示。在评估 Llama-2 13B 时,这些趋势保持不变,如图 3 所示。【NLP】DeepSpeed-FastGen:通过 MII 和 DeepSpeed-Inference 为LLM生成高通量文本_第6张图片

图 2:使用 Llama 2 70B(4 个 A100-80GB GPU 上的张量并行性)生成文本的吞吐量和延迟。对提示长度和生成长度应用正态分布,平均值分别为 1200/2600 和 128/60,方差为 30%

【NLP】DeepSpeed-FastGen:通过 MII 和 DeepSpeed-Inference 为LLM生成高通量文本_第7张图片图 3:使用 Llama 2 13B(A100-80GB GPU,无张量并行)生成文本的吞吐量和延迟。对提示长度和生成长度应用正态分布,平均值分别为 1200/2600 和 60/128,方差为 30%

3.有效吞吐量分析

在考虑首次令牌延迟和生成发生速率的有效吞吐量分析下,DeepSpeed-FastGen 提供的吞吐量比 vLLM 高出 2.3 倍。图 4 展示了 DeepSpeed-FastGen 和 vLLM 有效吞吐量的比较分析。每个标绘点表示从特定数量的客户端得出的有效吞吐量。随着我们扩大客户端数量,我们最初观察到有效吞吐量有所增加。然而,随着客户端数量接近系统容量,延迟也会显着增加,导致许多请求无法满足 SLA。因此,有效吞吐量将在某个时刻饱和或下降。从可用性的角度来看,需要多少客户端才能实现最大有效吞吐量并不特别相关;这条线的最高点就是最佳发球点。

【NLP】DeepSpeed-FastGen:通过 MII 和 DeepSpeed-Inference 为LLM生成高通量文本_第8张图片

图 4:DeepSpeed-FastGen 和 vLLM(Llama 2 70B/A100-80GB,在 4 个 A100-80GB GPU 上使用张量并行性)的有效吞吐量。对提示长度和生成长度应用正态分布,平均值分别为 2600 和 60, 30% 方差)

当 vLLM 抢占正在生成的先前请求时,生成延迟会显着增加。这导致 vLLM 的有效吞吐量显得低于其直接测量的吞吐量。在 vLLM 的峰值时,有效吞吐量为 0.63 个查询/秒,大约 28% 的请求未能满足 4 个令牌/秒的 SLA。在相同的 SLA 下,DeepSpeed-FastGen 实现了 1.42 个查询/秒(不到 1% 的请求未能满足 SLA),比 vLLM 高 2.3 倍。

4.代币级别时序分析

图 5 显示了生成过程的 P50、P90 和 P95 延迟。vLLM 和 DeepSpeed-FastGen 都表现出相似的 P50 延迟,但 vLLM 表现出 P90 和 P95 的延迟明显更高。对于 P95 延迟,DeepSpeed-FastGen 实现了 3.7 倍的降低。

出现这种差异的原因是,当 vLLM 抢占正在进行的生成以处理新提示时,vLLM 的生成延迟会出现明显的峰值。相比之下,DeepSpeed-FastGen 通常会同时处理先前请求的提示和生成,从而导致生成延迟更加一致。【NLP】DeepSpeed-FastGen:通过 MII 和 DeepSpeed-Inference 为LLM生成高通量文本_第9张图片

图 5:Llama 2 70B/A100-80GB 在 4 个 A100-80GB GPU、16 个客户端上使用张量并行性时的每个令牌生成延迟。对提示长度和生成长度应用正态分布,平均值分别为 2600 和 128,方差为 30%。

5.使用负载平衡的可扩展性

DeepSpeed-FastGen 提供副本级负载平衡,可在多个服务器之间均匀分配请求,使您能够轻松扩展应用程序。

图 6 说明了使用负载均衡器和最多 16 个副本时 DeepSpeed-FastGen 的可扩展性。请注意,我们使用 4 个 A100 GPU 来计算 Llama 2 70B 模型。我们总共使用了 8 个节点来运行 16 个副本。结果表明 DeepSpeed-FastGen 的可扩展性近乎完美。假设单个副本的吞吐量为 1.46 个查询/秒,则 16 个副本的吞吐量达到 23.7 个查询/秒,与单个副本相比线性增长 16 倍。【NLP】DeepSpeed-FastGen:通过 MII 和 DeepSpeed-Inference 为LLM生成高通量文本_第10张图片

图 6:使用负载平衡功能的可扩展性。对提示长度和生成长度应用正态分布,平均值分别为 2600 和 60,方差为 30%

6.其他硬件平台

除了对A100的深入分析之外,我们还提供了H100和A6000的额外基准测试结果。在 A6000 和 H100 上观察到与 A100 相同的性能趋势。【NLP】DeepSpeed-FastGen:通过 MII 和 DeepSpeed-Inference 为LLM生成高通量文本_第11张图片

图 7:使用 8 个 H100 GPU 的 Llama 2 70b 的吞吐量-延迟曲线和有效吞吐量。对提示长度和生成长度应用正态分布,平均值分别为 2600 和 60,方差为 30%【NLP】DeepSpeed-FastGen:通过 MII 和 DeepSpeed-Inference 为LLM生成高通量文本_第12张图片

图 8:使用 A6000 的 Llama 2 7b 的吞吐量-延迟曲线和有效吞吐量。对提示长度和生成长度应用正态分布,平均值分别为 2600 和 60,方差为 30%

五、DeepSpeed-FastGen:实现和使用

DeepSpeed-FastGen 是DeepSpeed-MII和DeepSpeed-Inference的协同组合,如下图所示。这两个软件包共同提供了系统的各种组件,包括前端 API、使用 Dynamic SplitFuse 调度批次的主机和设备基础设施、优化的内核实现以及构建新模型实现的工具。【NLP】DeepSpeed-FastGen:通过 MII 和 DeepSpeed-Inference 为LLM生成高通量文本_第13张图片

开始使用我们的 DeepSpeed-FastGen alpha 版本的最快方法是:

pip install deepspeed-mii

请按照我们的入门指南了解更多详细信息。有关使用和报告问题,请使用DeepSpeed-MII Github 存储库。

1.支持的型号

目前,我们在此 DeepSpeed-FastGen 的 alpha 版本中支持以下模型架构:

  • LLaMA和LLaMA-2
  • Mistral
  • OPT

当前所有模型都利用后端的HuggingFace API 来提供模型权重和模型相应的标记生成器。

我们计划在首次发布后的未来几周和几个月内添加更多模型。如果您希望支持特定的模型架构,请提出问题并告知我们。

2.部署选项

下面的所有示例都可以在DeepSpeedExamples中运行。安装后,您有两个部署选项:交互式非持久管道或持久服务部署:

非持久管道

非持久管道部署是一种很好且快速的入门方式,只需几行代码即可完成。非持久模型仅在您运行的 python 脚本期间存在,但对于临时交互式会话很有用。

from mii import pipeline
pipe = pipeline("mistralai/Mistral-7B-v0.1")
output = pipe(["Hello, my name is", "DeepSpeed is"], max_new_tokens=128)
print(output)
持久部署

持久部署非常适合长时间运行的生产应用程序。持久部署使用轻量级 GRPC 服务器,可以使用以下 2 行创建该服务器:

import mii
mii.serve("mistralai/Mistral-7B-v0.1")

由于 DeepSpeed-MII 的内置负载均衡器,上述服务器可以同时被多个客户端查询。创建客户端也只需要两行代码:

client = mii.client("mistralai/Mistral-7B-v0.1")
output = client.generate("Deepspeed is", max_new_tokens=128)
print(output)

当不再需要持久部署时,可以终止它:

client.terminate_server()

3.高级安装信息

为了易于使用并显着减少许多项目在此领域所需的冗长编译时间,我们通过一个名为DeepSpeed-Kernels 的新库分发了一个预编译的 Python 轮,涵盖了我们的大多数自定义内核。我们发现该库在具有计算能力 8.0+ (Ampere+)、CUDA 11.6+ 和 Ubuntu 20+ 的 NVIDIA GPU 的环境中非常便携。在大多数情况下,您甚至不需要知道该库的存在,因为它是 DeepSpeed-MII 的依赖项,并将随其一起安装。但是,如果出于某种原因您需要手动编译我们的内核,请参阅我们的高级安装文档。

六、尝试DeepSpeed-FastGen

我们非常高兴分享这个 DeepSpeed-FastGen alpha 版本。

  • 要开始使用,请访问我们的 DeepSpeed-MII GitHub 页面:GitHub 登陆页面

你可能感兴趣的:(自然语言处理(NLP),LLMs(大型语言模型),人工智能(AI),人工智能,llama,自然语言处理)