vLLM 更新简览
想学习 vllm,但发现它的更新速度实在是太快了,在主线上一天能有十几个 commit,版本迭代得也非常快,于是有一个想法,先从项目更新的视角来简单看一下 vllm,也好理解每个版本都变动了什么。
水平有限,只作为学习笔记,有错误的地方敬请谅解。
问世
产业界
第一个提交时间:2023.02.09
submission(SOSP'23 提交截止)时间:2023.04.17
v0.1.0 官方发布时间:2023.06.20
相关博客:https://blog.vllm.ai/2023/06/20/vllm.html
代码行数:7K(使用 tokei 统计 Python 的代码行数取近似)
学术界
论文:Efficient Memory Management for Large Language Model Serving with PagedAttention
Arxiv 时间:2023.09.12,后被 SOSP'23 接收,发表时间:2023.10.23
Meetup 内容总结
PPT 可以从官网获得:https://docs.vllm.ai/en/latest/community/meetups.html
第一次(2023.10.05)
提出 vLLM 的目标:Build the fastest and easiest-to-use open-source LLM inference & serving engine
介绍 PagedAttention:An attention algorithm that allows for storing continuous keys and values in non-contiguous memory space. (像操作系统的虚拟内存一样管理 KV cache)
有两种 API:LLM 类和 OpenAI 兼容服务器
本次汇报的目标
-
理解 vLLM 如何处理请求并生成输出,以及后续内容的背景。总结:
- 核心组件:LLMEngine
- 使用集中控制器控制分布式的 workers
- 在每次迭代时调度器会准备好请求
- workers 使用 PagedAttention 运行模型
-
了解可以在哪里进行修改以进行特定的贡献
这里可以看 图解大模型计算加速系列:vLLM 源码解析 1,整体架构 进行补充理解。
vLLM 自发布以来的更新
-
支持了更多的模型:在此不列举。
-
优化了性能:通过以下两个优化,v0.2.0 相比 v0.1.7 吞吐量提升了 66%
- 使用缓存和增量更新来减少 de-tokenization (Token IDs 转文本)过程中 CPU 的开销。
- 矢量化的采样器
-
确保了正确性和鲁棒性:看起来是在解决之前与 huggingface 输出不一致的问题
-
提高了易用性:减少了安装时间;与一些框架集成
-
代码重构:罗列了一些 PR
未来计划
-
优化延迟
- 轻量化运行时(Python/PyTorch 开销占了一半),两种解决方案:1、pytorch + cuda graphs;2、c++ 运行时
- 多进程结构:在进程间使用异步通信
- 推测解码:小模型生成多个 token,大模型验证评估
-
更好的量化支持
- 为不同量化方法开发通用抽象
- 实现各种量化方法(WIP:GPTQ,SmoothQuant,SqueezeLLM,TODO:GGML,GGUF, . . .)
- 优化量化后的算子性能
-
CUDA 级的优化(针对 PagedAttention kernel)
- 更好的工作划分(利用序列级并行)
- 高效的 MQA/GQA 支持
-
以下内容是第二优先级
- (高效)LoRA 支持
- AMD 支持
- MoE
- 流水线并行
第二次(2024.01.31)
总览
这部分和第一次 Meetup 基本一致
项目进展
自上一次 Meetup(间隔 118 天)之后的更新
-
支持了 20 多种不同的模型架构,覆盖了大部分主流大语言模型。获得了官方的 MoE 支持(Mixtral 和 DeepSeek)。
-
性能优化
- PagedAttention V2:从每个序列一个 SM 变成了每个序列分区一个 SM (1 SM per sequence partition)
- CUDA 图。这部分可以参考 浅谈 cuda graph 在 llm 推理中的应用,包括文中的参考文章。
- 分布式运行时优化:看起来是删去了 python 对象的序列化开销,worker 间使用 NCCL 通信
- 更快的 All-Reduce 内核:对小规模张量的优化
-
新特性
- AMD GPU 支持:下一阶段是对 MI300x 的性能优化
- Multi-LoRA 服务:不同 LoRA 的请求会放在同一批
- 量化支持:GPTQ、AWQ、SqueezeLLM、FP8-E5M2 KV Cache
- 前缀缓存:把通用前缀缓存到 paged memory 中,新请求可以直接使用而无需重复计算
- 其他提升
- CI/CD:每个 PR 现在都会在 GPU 上进行测试和跑分
- 官方预编译二进制文件和 Docker 镜像
- 批量完成 OpenAI API
- 大量的 bug 修复
未来计划
之前目标的达成度,这里放一张原图
提升方面的计划
-
性能优化:H100 和 MoE
-
调度优化:分块预填充和预填充分解
-
支持激活值量化
-
可扩展的调度器和内存管理器
-
torch.compile 特性的支持
特性方面的计划:
-
多种硬件支持:AWS Inferentia, Google TPU, Intel Gaudi, Intel GPU, Intel CPU
-
多模态模型支持
-
推测解码:对不同算法的广泛支持
对于 Speculative Decoding 的中译采用这篇综述的选择
-
自动前缀缓存
-
结构化的输出(JSON、regex、grammar)
第三次(2024.04.02)
总览
这部分和第一次 Meetup 也差不多。
总结了特征
项目进展
自上一次 Meetup(间隔 62 天)之后的更新,也就是 2 月和 3 月的进展。
-
模型支持:支持更多的模型架构;开始支持视觉语言模型:LLaVa
-
硬件支持:对 AMD 和 AWS Neuron 更好的支持;初步支持 Intel CPU;原型支持 Intel GPU 和 Intel Habana Gaudi
-
特性:
- 自动前缀缓存:有两个例子:多轮对话和共享系统 prompt
- 引导式解码:支持通过内容大纲、正则表达式、JSON 等,兼容 OpenAI
- 性能优化
- MoE 内核优化
- 在量化中集成 Marlin 内核
- 推测解码:小规模模型生成初稿。未来会支持其他方法:ngram,RAG,…
- 代码重构:Attention 后端(目的是可以为不同硬件和模型轻松插入不同的 attention 实现);模型执行器(目的是可以简单地加入新硬件支持并且把代码和硬件架构分离)
- 开源社区的快速发展
未来计划
高层次目标
-
广泛的模型支持:Encoder-decoder 模型(T5, Whisper, bge);混合架构(Jamba);更多视觉模型
-
出色的硬件支持:持续支持和积极协作的硬件有
- GPUs: NVIDIA, AMD, Intel GPU
- Tensor Accelerators: Google TPU, AWS Inferentia, Habana Gaudi
- CPU: Intel/AMD CPU
-
生产级别的引擎
- 推测解码框架:添加多种算法;支持自定义;探索 Medusa/Eagle
- 分块预填充度器
- 功能质量提升(Quality of Life Features):更快的模型加载;更好的指标和日志;API 服务器性能
-
性能优化:
- 通过 FlashInfer 和 OpenAI Triton 提升内核性能
- 量化:FP8 格式支持;通过 Marlin 内核改进仅权重量化;激活值量化框架(W8A8, FP8 等)
- 引导式解码优化
-
可扩展架构
- 原型流水线并行
- 可扩展内存管理器
- 可扩展调度器
- torch.compile 调研
-
强大的开源社区支持
- 持续的基准测试(急切需要资源!)
- nightly 安装包和 Docker 镜像
- 承诺每两周发布一次
剩余的 PPT 内容是 Roblox 的在线服务性能基准测试。
第四次(2024.06.11)
vLLM 简介
还是和之前的差不多,这里再放一张新图,详细地列举了已使用的推理优化技术。
项目进展
自上一次 Meetup(间隔 70 天)之后的更新
-
广泛的模型支持:Deepseek MoE、Gema、StarCoder2、Qwen2 MoE 等等
-
OpenAI API 兼容性:添加嵌入式 API;支持 OpenAI 批处理文件格式;对 tool_use 的初始支持
-
OpenAI Vision API 兼容性:围绕多模态模型的基础设施进行广泛的重构,以改善用户和开发人员的体验;与 OpenAI Vision API 的端到端服务兼容性
-
多样化的硬件支持:
- 已经支持:NVIDIA GPU、AMD GPU、AWS Neuron、x86 CPU
- 正在开发:Intel GPU、Google TPU、Intel Gaudi
-
功能亮点(已准备好测试和投入生产使用,并且会在之后的版本中默认启用):
- 分块预填充:以首个 token 产生时间为代价换取 token 间延迟(第一个 token 变慢,但整体更流畅)
- FP8 量化:以一定的精度为代价换取更低的延迟。
- 前缀缓存:以更高的内存占用为代价换取更低的延迟。
- 推测解码:以更高的计算成本为代价换取更低的延迟。
-
持续优化
- SOTA 内核:集成 FlashAttention 和 FlashInfer
- GPU 通信:NCCL,自定义 allreduce,用于分布式推理
- 更好的架构:基于多进程的 GPU 执行器
-
其他提升
- 易用性:集中管理并文档化的环境变量
- 持续的性能优化:
- 减少每步调度的开销
- 自动前缀缓存优化
- 内核调优
未来计划
主线内容和第四次 Meetup 的差不多,分别是
- 广泛的模型支持
- 出色的硬件支持
- 生产级别的引擎
- 性能优化:
- 可扩展架构
- 强大的开源社区支持
有一张图进行总结
推测解码深入解析
这里推荐一篇综述:LLM 推理加速新范式!推测解码(Speculative Decoding)最新综述,PPT 中的内容就是简要介绍一下推测解码,在 vllm 中的应用与优化。
第五次(2024.07.24)
vLLM 简介
与第四次相同
项目进展
自上一次 Meetup(间隔 43 天)之后的更新
-
Llama 3.1:与 Llama 3.1 合作,第一时间支持所有 Llama 3.1 模型,并给出了多样的选择来运行 Llama 3.1 405B,详情可见 博客。
-
新模型
- Transformer-based LLMs:Llama 3.1、Gemma 2、Deepseek V2、Mistral-Nemo
- State-Space Models:Jamba
- Vision Language Models:Phi3-Vision、PaliGemma、Fuyu-8B 、Chameleon
-
多样化的量化方法:W4A16、W8A16 等等。最新的支持可以看这里的表格。
-
CPU 卸载(v0.5.3 更新):只卸载模型权重,具有更低的执行时间。
-
流水线并行:从 v0.5.1 开始支持。
-
推测解码:支持 Medusa 和 MLP 推测器
-
TPU 硬件支持
-
详细的性能指标和比较,可见 https://perf.vllm.ai/
-
开发体验:新的 CLI(
vllm {serve, chat, complete});在 A100 和 H100 上加强的测试框架;发布优化
未来计划
只贴了一张现在的完成图,未来应该还是这几个方向
流水线并行深入解析
很奇怪,后续 PPT 没有内容了。这次 Meetup 的 PPT 页数只有 28 页。
第六次(2024.09.09)
vLLM 简介
与第四次相同
项目进展
自上一次 Meetup(间隔 47 天)之后的更新
-
有关 Llama 3.1 的内容和第五次相同
-
新模型
- 新 LLM:Nemotron models (Nemotron-3, Nemotron-4, Minitron)、Granite、Phi3.5 MoE、Jamba 1.5
- 新模型架构组件:Encoder decoder baselines;Native SSM baselines
-
多模态更新
- 特征
- 新多模态:语音(UltravoxModel from fixie.ai)
- 多图片接口,以 Phi-3.5-vision-instruct 为例
- 除了 PIL 图像外,还支持图像嵌入作为输入
- 优化
- 通过张量并行的移植实现为 ViT(CLIP、SigLIP)节省了内存
- 模型支持扩展
- 新 VLM:InternVL2, BLIP-2, MiniCPM-V
- 共计支持 11 个 LMM
- 即将到来
- 支持具有动态帧数的视频多模态
- 支持 Qwen2-VL
- 特征
-
量化更新
- 新格式:gguf,bitsandbytes,qqq (w4a8)
- 新推理内核:awq_marlin
- 推出 LLM Compressor,用于生成带有量化权重、激活值和键值缓存的模型。
-
性能提升
- 一系列增强措施,将吞吐量提高两倍。主要有
- 服务和引擎进程的分离(单个进程变成独立的两个进程)
- 多步调度(一次调度后可以运行多次 forward)
- 异步输出处理(输出和 forward 重叠)
- 聚焦于保持 GPU 高效运转并减少 CPU 开销
- 性能依然是首要任务
- Cody 将深入讲解每种技术!(应该是指后面的性能深入解析)
- 一系列增强措施,将吞吐量提高两倍。主要有
-
其他提升
- 对 python 对象进行缓存来减少分配
- 非阻塞的 CPU-GPU 间通信
- 为简单的采样参数提供快速路径
未来计划
Q3 Roadmap 图和第五次相比只多完成了 Model Support 中的 Encoder-decoder
-
torch.compile
- TPU 后端已经将 torch.compile 集成为始终可用的核心功能
- 但 CUDA 后端仍不稳定,正在与 PyTorch 团队积极合作
- 目标是始终启用 torch.compile,同时自动决定使用哪些组件,比如零开销的 Dynamo 和 Inductor
-
KV Cache 传输
-
为什么选择 KV 传输:因为这是一种无痛添加新功能的方式
- 分离的预填充
- 连接(多个)vLLM 到 KV 缓存数据库(例如 Redis 数据库)
-
提供了两个 API 在 KV 生产者进程和 KV 消费者进程之间传输 KV,在此不具体讲,可以简单看一下图
1 2buffer(tokens, roi, key, value) → None drop_select(tokens, roi) → Optional[tokens, roi, key, value]
-
-
重构 vLLM 以获得更干净的内核
- 总体目标:最小化 GPU 空闲时间和简化代码
- 异步调度:异步输出处理和多步调度的推广/简化
- 前缀集中缓存的设计(Prefix caching-centric design):默认启用前缀缓存;使用它来优化并行采样和重计算;使用 cascade inference 内核
-
TPU 后端更新
- 新特征
- 多主机张量并行推理
- 支持 GKE(Google Kubernetes Engine)
- Int8 量化(开发中)
- 视觉-语言模型支持(开发中)
- 性能优化
- 异步输出处理
- 减少 Dynamo 开销
- 减少 PyTorch/XLA 桥接开销
- 多步调度(开发中)
- 新特征
性能深入解析
性能分析
以往的 LLM 服务都是 GPU bound,但现在已经不是了(因为有了更强大的 GPU,比如 A100,H100,B100 等等)
以下是在一张 H100 上运行 Llama-3.1-8B 的延迟分解
见解:CPU 开销高;开销(API 服务器和 CPU 进程)在关键路径上。
分离 API 服务器和引擎进程
目的:将 API 服务器开销从关键路径中移除。
集成挑战
- 进程内套接字的多路复用
- dealer 套接字的输出流式传输
- 高水位标记(防止过载)
- 使用增量数据降低进程间通信开销
有非常多的优化可以做,并欢迎贡献!
多步调度
目的:在调度上避免一些 CPU 开销
Beta 于 v0.6.0 发布,还有一些特性没有被支持。
异步输出处理
目的:将 CPU 开销从关键路径中移除。
可以有 12.5% 的性能提升
PPT 中对于以上 3 种优化都没有详细的说明
其他提升
和前文项目进展中的其他提升一致
基准测试(v0.5.3 vs v0.6.0)
在单卡吞吐量上最高有 2.7x 的提升,延迟(TPOT)下降了 79% 。PPT 中还有几张性能比较图表在这里不展开描述。
下一步
- API 服务器:进一步增强功能并支持更高的健壮性
- 多步调度:简化流程并演变为完全异步的调度方式。
- 异步输出处理:标准化并简化流程。
- Python 开销:持续监控并研究优化方法。
第七次(2024.11.14)
年度总结
PPT 中比较简单,只是罗列了一下。(具体内容还得靠讲)
-
模型支持
- Transformer-like LLMs (e.g., Llama)
- Mixture-of-Expert LLMs (e.g., Mixtral)
- Multi-modal LLMs (e.g., LLaVA)
- State-Space Models (e.g., Jamba)
- Embedding Models (e.g. E5-Mistral)
- Reward Models (e.g. Qwen2.5-Math-RM)
-
硬件支持
- NVIDIA GPU
- AMD GPU
- AWS Neuron
- Intel CPU/GPU
- Google TPU
- Intel Gaudi
-
模型性能
- 深度优化至 CUDA 内核级
- 多功能 CUDA 图支持
- 广泛支持量化方法
- 最先进的量化内核
-
引擎特征
- 分块预填充
- 推测解码
- 自动前缀缓存
- 多 LoRA 服务
- 结构化输出
- 可观测性
-
分布式系统架构
- 张量并行
- 流水线并行
- CPU 卸载
- 自定义 All-Reduce
- 异步张量并行和 Flux 矩阵乘法内核
-
开源社区情况
2025 年的计划
V1 深入解析
什么是 vLLM V1
基于 V0(当前版本)的经验教训,重新构建 vLLM 的“核心”
不更改的:用户 API;模型;GPU 内核;实用工具函数等
改变的:调度器;内存管理器;模型运行器;API 服务器等
为什么需要 V1
vLLM 横向扩展(支持多种模型、丰富的功能特性、多样化的硬件后端)做的很好,但纵向整合(各功能独立开发,缺乏整合、很难将各种优化方案在各种模型上结合起来)不行,并且在过去的 1.5 年里,vLLM 累积了不少技术债务。
V1 的目标和非目标
目标
- 非常简单和容易修改的代码库
- CPU 几乎零开销的高性能
- 结合所有的关键优化技术,并默认启用它们
- 重新审视 V0 中的设计决策
非目标
- 压榨最后一点性能
- 最开始就支持各种模型和功能
vLLM V1 中的关键改变
-
简化的调度器
- prefill 和 decode 的统一
- 在 V1 中,没有 prefill 和 decode 的概念
- 调度器只考虑当前请求有多少 token (prompt + output),以及它们有多少是已经处理过的
- 足够的灵活来支持复杂的情景
- 使用前缀缓存实现高效的抢占后恢复
- 当 KV cache 满之后,vLLM 会抢占某个请求
- 前缀缓存可以在恢复请求时,不用重新计算其所有的 token
- prefill 和 decode 的统一
-
增量输入准备(连续批处理)
- 在 V0 中,输入张量在每个 step 都从头开始重新创建
- 在 V1 中,输入张量被缓存,每个 step 中只修改不同的地方
-
分段 CUDA 图
- V0:将整个模型捕捉到 CUDA 图中
- 优点:模型执行时几乎没有 CPU 开销
- 缺点:模型必须是静态的,且不能包含 CPU 操作
- V1:混合方法
- 在 Eager 模式的 PyTorch 中执行注意力操作,提供完全的灵活性
- 对其他操作使用 CUDA 图,避免大部分 CPU 开销
- V0:将整个模型捕捉到 CUDA 图中
-
增强的 API 服务器
- 使用后台忙循环(busy loop)作为主要执行循环
- 确保引擎不会因为等待 API 服务器而暂停
- 将解码器放在单独的进程中
- 解码过程不属于关键路径
- 如果解码器检测到停止字符串,它会向引擎发送中止信号(总体过程是异步)
- 使用后台忙循环(busy loop)作为主要执行循环
-
更高效的前缀缓存
- 在 V0 中,前缀缓存导致了较高的 CPU 开销
- LRU 驱逐器在每次块分配时需要花费 O(N) 时间,其中 N 是空闲块的数量。
- 在 V1 中使用了更高效的数据结构
- 使用双向链表和字典,实现 O(1) 时间的块分配
- 初始化后不再创建新的 python 对象
- 即使缓存命中率为 0%,其性能下降也仅为 0-1%
- 在 V0 中,前缀缓存导致了较高的 CPU 开销
-
VLMs 的细粒度调度
- 引入嵌入式缓存以解耦视觉编码器和 LLM 解码器
- 视觉编码器将输出存储到嵌入缓存中
- 语言模型从嵌入缓存中获取 “soft token”
- 分别调度视觉编码器和 LLM 解码器
- 引入了编码器预算(encoder budget),以避免在同一步骤中处理太多图像(限制了每一步的延迟)
- 调度器精确地跟踪输入之间的依赖关系,并考虑利用它们进行调度决策
- 引入嵌入式缓存以解耦视觉编码器和 LLM 解码器
V1 引擎的性能
- 吞吐量上与 V0 + 8-step 调度一致
- 比 V0 + 8-step 具有更低的 TTFT(Time to first token) 和 TPOT(time per output token)
V1 当前状态
-
目前处于实验阶段(代码位于 vllm/v1)
-
设置 VLLM_USE_V1=1 即可使用 V1 引擎(与 V0 使用相同的用户 API)
-
目前仅支持 NVIDIA GPU
-
支持的模型
- Decoder-only 的 Transformer,比如 Llama,Mixtral
- Llava 风格的 VLMs,比如 Llava,Phi3v
-
特征
- 支持:分块预填充,前缀缓存
- 不支持:张量并行(正在开发中),推测解码,LoRA 等
V1 推出计划
在接下来的 2-4 周内,计划将 V1 设为默认引擎,对于不支持的模型和功能,将回退到 V0。之后会逐步扩大 V1 的支持范围。
V0 和 V1 将在一段时间内共存:
- V0 用于广泛的模型和功能支持
- V1 提供高性能和简化代码
V1 将结合更多的优化方案。
torch.compile 深入解析
为什么我们需要 torch.compile
没有编译器时的优化(融合残差链接和归一化),提高了计算效率但代码可读性和可维护性变差
这会导致维护灾难,根本没有模块化:一些理论公式上的改动看起来很简单,但在实现中可能需要投入大量的工程工作。
而 torch.compile 就是在模块化、可维护性和性能之间寻求一种平衡,在不牺牲代码可维护性的前提下提升性能。
我们应该怎么使用 torch.compile
-
连续批处理:vLLM 计算中使用了连续批处理的方法,原先在中间过程的 KV Cache 这里需要跨 token 进行操作,这对编译器而言是噩梦。改进后利用了一个“黑盒”自定义算子来隐藏复杂性,将复杂的跨 token 操作包装成一个看起来像单 token 的操作,使其对编译器友好。
-
优化 PyTorch Dynamo 的运行机制,消除重复检查带来的额外开销
-
通过分段编译和零拷贝 CUDA 图结合的方式,分别优化 token-wise 和跨 token 的操作
-
符号化和形状专用化
推出计划
-
vLLM 的 torch.compile 集成承诺在开始处理流量时不会触发任何编译。
- 我们不希望任何来自用户的请求触发编译(并导致整个引擎被阻塞数十秒!)。
-
vLLM 的 torch.compile 集成承诺提供最佳的编译控制。
- 编译越多,性能越好
- 每一次编译都不会被浪费。
-
torch.compile 集成功能现在已经在主分支中完成
- 正在清理并整合相关的标志选项
- 将逐步向用户推出所有功能。
- 下一次发布将支持基础的编译功能(以最少的编译时间为目标)。
-
未来步骤包括:
- 缓存编译结果以便在不同机器上复用(实现快速部署)。
- 等等
代码行数变动
可以看到从去年的 v0.1.0(2023.06.20)到现在最新的 v0.6.4(2024.11.15),代码行数从 7 千行增加到了现在的将近 18 万行。间隔 514 天,平均每天增加了 334 行新代码,可以看到发展得非常快。
本站不记录浏览量,但如果您觉得本内容有帮助,请点个小红心,让我知道您的喜欢。