vLLM:高吞吐量 LLM 推理系统的结构
在这篇文章中,我将逐步介绍构成现代高吞吐量 LLM 推理系统的所有核心系统组件和高级功能。特别是,我会详细讲解 vLLM [1] 的工作原理。这篇文章是一个系列的第一篇。它从宽泛的角度入手,然后逐层深入(遵循反金字塔的方法),以便让你能够形成准确的整体系统的高层次思维模型,而不会淹没于细节中。后续的文章将深入探讨特定的子系统。这篇文章分为五个部分:LLM 引擎与引擎核心:vLLM 的基本原理(调度、分页注意力、连续批处理等) 高级功能:分块预填、前缀缓存、引导和推测解码、分离的 P/D 扩展 从单 GPU 到多 GPU 执行的扩展 服务层:分布式/并发网络框架 基准测试和自动调优:测量延迟和吞吐量 📝 说明 分析基于提交 42172ad(2025 年 8 月 9 日)。 目标受众:任何对现代 LLM 引擎如何工作感到好奇的人,以及那些有兴趣为 vLLM、SGLang 等贡献的人。 我会专注于 V1 引擎。我也探讨了 V0(现已弃用),这对了解项目的发展过程是有价值的,而且许多概念依然适用。关于 LLM 引擎/引擎核心的第一部分可能有点压倒性/枯燥——但博客的其余部分有大量的示例和可视化内容。 :) LLM 引擎和引擎核心 LLM 引擎是 vLLM 的基本构建块。仅凭它已能够实现高吞吐量的推理,但仅限于离线环境。你还不能通过网络向客户提供服务。我们将使用以下离线推理示例作为我们运行的示例(改编自 basic.py)。 from vllm import LLM , SamplingParams prompts = [ "你好,我的名字是" , "美国总统是" , ] sampling_params = SamplingParams ( temperature = 0.8 , top_p = 0.95 ) def main ( ) : llm = LLM ( model = "TinyLlama/TinyLlama-1.1B-Chat-v1.0" ) outputs = llm . generate ( prompts , sampling_params ) if __name__ == "__main__" : main ( ) 📝 环境变量: VLLM_USE_V1="1" # 我们正在使用引擎 V1 VLLM_ENABLE_V1_MULTIPROCESSING="0" # 我们正在单进程下运行 此配置是:离线(没有 Web/分布式系统框架)同步(所有执行都发生在单个阻塞进程中)单 GPU(没有数据/模型/流水线/专家并行性;DP/TP/PP/EP = 1)使用标准变换器 [2](支持混合模型如 Jamba 需要更复杂的混合 KV 缓存内存分配器) 从这里开始,我们将逐步构建一个在线、异步、多 GPU、多节点的推理系统——但仍在服务一个标准变换器。在这个示例中,我们做两件事情: 我们: 实例化一个引擎 调用生成方法,从给定的提示中进行采样 让我们开始分析构造函数。 LLM 引擎构造函数 引擎的主要组件包括: vLLM 配置(包含所有调整模型、缓存、并行性的旋钮)处理器(通过验证、令牌化和处理将原始输入转换为 EngineCoreRequests)引擎核心客户端(在我们的运行示例中,我们使用的是 InprocClient,这基本上等同于 EngineCore;我们将逐步构建到 DPLBAsyncMPClient,以便进行大规模服务)输出处理器(将原始 EngineCoreOutputs 转换为用户看到的 RequestOutput) 📝 注意:由于 V0 引擎已被弃用,类名和细节可能会发生变化。我会强调核心思想,而不是精确的函数签名。我将抽象一些但不是所有的细节。引擎核心本身由多个子组件构成:模型执行器(在模型上驱动前向传递,我们目前处理的是 UniProcExecutor,它在单个 GPU 上有一个单一的工作进程)。我们将逐步构建到支持多个 GPU 的 MultiProcExecutor 结构化输出管理器(用于引导解码——我们稍后会介绍)调度器(决定哪些请求进入下一个引擎步骤)——它进一步包含:策略设置——可以是 FCFS(先到先服务)或优先级(优先请求优先服务)等待和运行队列 KV 缓存管理器——分页注意力的心脏 [3] KV 缓存管理器维护一个 free_block_queue——一个可用 KV 缓存块的池(通常是几十万的数量,具体取决于 VRAM 大小和块大小)。在分页注意力期间,这些块作为索引结构,将令牌映射到它们计算的 KV 缓存块。 本节中描述的核心组件及其关系 标准变换器层的块大小(非 MLA [4])计算如下: 2(键/值)* 块大小(默认=16)* kv 头数 * 头部大小 * dtype_num_bytes(例如,bf16 为 2) 在创建模型执行器时,会创建一个 Worker 对象,并执行三个关键过程。(稍后,在 MultiProcExecutor 中,这些过程将在不同 GPU 上的每个工作进程上独立运行。)初始化设备:分配一个 CUD
本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。
☕请我喝杯咖啡