【论文解读】DistServe:Disaggregating Prefill and Decoding for Goodput-optimized Large Language Model Servi

DistServe是北大Xin Jin组和USD合作的研究,已被OSDI‘24接收。它通过分解预填充和解码计算,消除干扰,共同优化资源分配和并行策略,提高大型语言模型服务性能。评估显示,相比现有系统,它能服务更多请求或满足更严格SLO,同时将多数请求保持在延迟限制内。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DistServe: Disaggregating Prefill and Decoding for Goodput-optimized Large Language Model Serving

这篇论文是北大Xin Jin组和USD合作的,已经被OSDI‘24接收。主要思路是将一个推理请求的prefill和decoding分解进行batch,从而最优化goodput。

摘要

DistServe 通过分解预填充和解码计算来提高大型语言模型 (LLM) 服务的性能。 现有的 LLM 服务系统将两个阶段colocate,并批量计算所有用户和请求的预填充和解码。 我们发现这种策略不仅会导致强烈的预填充解码干扰,而且还会耦合两个阶段的资源分配和并行计划。 LLM 应用程序通常强调每个阶段的单独延迟:预填充阶段的第一个token时间 (TTFT) 和解码阶段每个请求的每个输出token时间 (TPOT)。 在存在严格的延迟要求的情况下,现有系统必须优先考虑一种延迟而不是另一种,或者过度配置计算资源来满足这两种延迟。
DistServe 将预填充和解码计算分配给不同的 GPU,从而消除预填充和解码干扰。 考虑到应用程序的 TTFT 和 TPOT 要求,DistServe 共同优化为每个阶段量身定制的资源分配和并行策略。 DistServe 还根据服务集群的带宽来colocate两个阶段,以最大程度地减少因分解而导致的通信。 因此,DistServe 在每个 GPU 上的 TTFT 和 TPOT 限制内可提供的最大速率方面显着提高了 LLM 服务性能。 我们的评估表明,在各种流行的 LLM、应用程序和延迟要求上,与最先进的系统相比,DistServe 可以服务 4.48 倍以上的请求或 10.2 倍更严格的 SLO,同时将超过 90% 的请求保持在延迟限制内。

Contributions:

  • 识别现有 LLM 服务系统中的预填充-解码干扰和资源耦合问题,并建议分解预填充和解码阶段。
  • 设计一种新的placement算法来自动选择预填充和解码instances的goodput最佳模式。
  • 使用真实的workloads对DistServe做了一个全面的实验验证。

2.Background and Motivation

LLM 服务遵循客户端-服务器架构:客户端将文本序列作为请求提交给服务器; 服务器在 GPU 上托管 LLM,对请求运行推理,并将生成结果响应(或流式传输)回客户端。 如第 1 节中所述,由于独特的预填充解码过程,LLM 服务可能会对 TTFT 和 TPOT 施加激进的服务级别目标 (SLO),具体取决于应用程序的需求。 服务系统必须满足两个 SLO,同时最大限度地降低与昂贵 GPU 相关的成本。 换句话说,我们希望服务系统能够最大限度地提高每秒服务的请求数,并遵循每个配置的 GPU 的 SLO 实现目标——最大限度地提高每个 GPU 的吞吐量。 接下来,我们详细介绍 LLM 推理计算(第 2.1 节)并讨论 LLM 服务的现有优化(第 2.2 节)。

2.1 LLM inference

现代LLMs [32, 43] 在给定输入序列的情况下预测下一个token。 该预测涉及计算序列中每个token的隐藏表示。 LLM 可以采用可变数量的输入token并并行计算其隐藏表示,并且其计算工作量随着并行处理的token数量而超线性增加。 无论输入token数量如何,计算都需要大量 I/O 将 LLM 权重和中间状态从 GPU 的 HBM 移动到 SRAM。 此过程对于不同的输入大小是一致的。

预填充步骤处理新序列,通常包含许多token,并同时处理这些token。 与预填充不同,每个解码步骤仅处理上一步生成的一个新令牌。 这导致两个阶段之间存在显着的计算差异。 当处理不简短的用户prompt时,预填充步骤往往受计算限制。 例如,对于 13B LLM,计算 512 个token序列的预填充会导致 A100 计算受限。 模型越大,将预填充步骤转为计算限制所需的序列就越短(请参阅第 3.1 节)。 相比之下,解码阶段尽管每步仅处理一个新令牌,但会产生与预填充阶段类似水平的 I/O,从而使其受到 GPU 内存带宽的限制。

在这两个阶段中,每个token位置都会生成中间状态,称为 KV cache [28],在后续解码步骤中再次需要这些状态。 为了避免重新计算它们,它们被保存在 GPU memory中。 由于在memory中共享 LLM 权重和 KV 缓存,大多数 LLM 推理引擎选择colocate预填充和解码阶段到GPU,尽管它们具有独特的计算特性。

2.2 LLM Serving Optimization

在实时在线服务中,会出现多个请求,并且必须在 SLO 内提供服务。 批处理和并行化计算是实现 GPU 低延迟、高吞吐量和高利用率的关键。

**Batching.**当前的服务系统 [8,28,45] 使用称为连续批处理的批处理技术。 此方法通过对正在进行的请求进行解码来批量预填充新请求。 它提高了 GPU 利用率并最大限度地提高了整体系统吞吐量——所有用户和请求每秒生成的tokens。 然而,正如第 1 节中提到的以及稍后第 2.3 节中详细阐述的,这种方法会导致 TTFT 和 TPOT 之间的权衡。 连续批处理的高级变体 [8] 试图通过分段预填充和附加解码作业来平衡 TTFT 和 TPOT,以避免超出 GPU 性能限制 - 但本质上,它是用 TTFT 换取 TPOT。 总之,批量预填充和解码总是会导致 TTFT 或 TPOT 的妥协。

Model parallelism. 在LLM服务中,模型并行性通常分为算子内并行性和算子间并行性[29,39,50]。 两者都可以用于支持更大的模型,但可能会以不同的方式影响服务性能。 算子内并行性将计算密集型算子(例如矩阵乘法)划分到多个 GPU 上,从而加速计算,但会导致大量通信。 它减少了执行时间,从而减少了延迟,特别是对于预填充阶段的 TTFT,但需要 GPU 之间的高带宽连接(例如 NVLink)。 运算符间并行性将 LLM 层组织为多个阶段,每个阶段在 GPU 上运行以形成管道。 由于级间通信,它会适度增加执行时间,但会随着每个添加的 GPU 线性扩展系统的速率容量。 在本文中,我们揭示了模型并行性的另一个好处:通过缩短执行时间来减少预填充和解码阶段的排队延迟。 我们将在第 3 节中进一步探讨这一点。 除了模型并行性之外,复制模型实例(无论其模型并行性配置如何)都会线性扩展系统的速率容量。

这些并行策略创建了一个复杂的优化空间,需要根据应用程序的延迟要求进行仔细权衡。

2.3 Problems and Opportunities

与现有系统一样,对预填充和解码计算进行colocate和批处理以最大化整体系统吞吐量,这对于服务提供商来说是具有成本效益的。 然而,在存在 SLO 的情况下,由于下面讨论的问题,当前的方法很难保持高服务质量和低成本。

Prefill-decoding interference. 如图 2 所示,向一批解码请求添加单个预填充作业会显着减慢这两个过程,从而导致 TTFT 和 TPOT 显着增加。 具体来说,批次中的解码任务必须等待更长的预填充作业完成,从而延长了TPOT;

### 大模型中的Prefill与Decode过程 #### Prefill 过程 在大模型处理输入序列时,Prefill 阶段负责初始化计算环境并执行初步的前向传播操作。此阶段的主要任务是对给定提示词(Prompt)进行编码,并生成初始隐藏状态表示。具体来说: - 对于每一个新请求,系统会先加载预训练好的权重参数。 - 接着将用户提供的文本转换成对应的token ID列表形式。 - 使用Transformer架构下的自注意力机制来捕捉上下文依赖关系[^1]。 ```python def prefill(prompt_tokens, model_weights): hidden_states = initialize_hidden_state(model_weights) attention_outputs = apply_self_attention(hidden_states, prompt_tokens) return attention_outputs ``` #### Decode 过程 当完成Prefill之后进入Decode环节,在这个过程中主要关注如何高效地逐个生成后续Token直到满足特定条件为止。为了加速解码速度通常采用如下策略: - 缓存已计算过的Key/Value矩阵以减少重复运算量。 - 利用Vulkan或CUDA等硬件特性来进行批量并行化处理。 - 实施Beam Search算法提高最终输出的质量而非单纯贪心选取最高概率项[^3]。 ```python def decode(current_token_id, cached_kv_matrices, beam_width=5): next_probabilities = compute_next_token_probs( current_token_id, cached_kv_matrices ) top_k_candidates = select_top_k(next_probabilities, k=beam_width) best_sequence = find_best_path(top_k_candidates) return best_sequence ``` 通过上述方法可以在保持较高精度的同时显著提升推理效率,使得大规模语言模型能够更加实时响应用户的查询需求[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wychen_sunshine

你的鼓励是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值