jklincn


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 如何处理请求并生成输出,以及后续内容的背景。总结:

    1. 核心组件:LLMEngine
    2. 使用集中控制器控制分布式的 workers
    3. 在每次迭代时调度器会准备好请求
    4. workers 使用 PagedAttention 运行模型
  • 了解可以在哪里进行修改以进行特定的贡献

这里可以看 图解大模型计算加速系列:vLLM 源码解析 1,整体架构 进行补充理解。

vLLM 自发布以来的更新

  1. 支持了更多的模型:在此不列举。

  2. 优化了性能:通过以下两个优化,v0.2.0 相比 v0.1.7 吞吐量提升了 66%

    1. 使用缓存和增量更新来减少 de-tokenization (Token IDs 转文本)过程中 CPU 的开销。
    2. 矢量化的采样器
  3. 确保了正确性和鲁棒性:看起来是在解决之前与 huggingface 输出不一致的问题

  4. 提高了易用性:减少了安装时间;与一些框架集成

  5. 代码重构:罗列了一些 PR

未来计划

  1. 优化延迟

    1. 轻量化运行时(Python/PyTorch 开销占了一半),两种解决方案:1、pytorch + cuda graphs;2、c++ 运行时
    2. 多进程结构:在进程间使用异步通信
    3. 推测解码:小模型生成多个 token,大模型验证评估
  2. 更好的量化支持

    1. 为不同量化方法开发通用抽象
    2. 实现各种量化方法(WIP:GPTQ,SmoothQuant,SqueezeLLM,TODO:GGML,GGUF, . . .)
    3. 优化量化后的算子性能
  3. CUDA 级的优化(针对 PagedAttention kernel)

    1. 更好的工作划分(利用序列级并行)
    2. 高效的 MQA/GQA 支持
  4. 以下内容是第二优先级

    1. (高效)LoRA 支持
    2. AMD 支持
    3. MoE
    4. 流水线并行

第二次(2024.01.31)

总览

这部分和第一次 Meetup 基本一致

项目进展

自上一次 Meetup(间隔 118 天)之后的更新

  1. 支持了 20 多种不同的模型架构,覆盖了大部分主流大语言模型。获得了官方的 MoE 支持(Mixtral 和 DeepSeek)。

  2. 性能优化

    1. PagedAttention V2:从每个序列一个 SM 变成了每个序列分区一个 SM (1 SM per sequence partition)
    2. CUDA 图。这部分可以参考 浅谈 cuda graph 在 llm 推理中的应用,包括文中的参考文章。
    3. 分布式运行时优化:看起来是删去了 python 对象的序列化开销,worker 间使用 NCCL 通信
    4. 更快的 All-Reduce 内核:对小规模张量的优化
  3. 新特性

    1. AMD GPU 支持:下一阶段是对 MI300x 的性能优化
    2. Multi-LoRA 服务:不同 LoRA 的请求会放在同一批
    3. 量化支持:GPTQ、AWQ、SqueezeLLM、FP8-E5M2 KV Cache
    4. 前缀缓存:把通用前缀缓存到 paged memory 中,新请求可以直接使用而无需重复计算
    5. 其他提升
      • CI/CD:每个 PR 现在都会在 GPU 上进行测试和跑分
      • 官方预编译二进制文件和 Docker 镜像
      • 批量完成 OpenAI API
      • 大量的 bug 修复

未来计划

之前目标的达成度,这里放一张原图

提升方面的计划

  1. 性能优化:H100 和 MoE

  2. 调度优化:分块预填充和预填充分解

  3. 支持激活值量化

  4. 可扩展的调度器和内存管理器

  5. torch.compile 特性的支持

特性方面的计划:

  1. 多种硬件支持:AWS Inferentia, Google TPU, Intel Gaudi, Intel GPU, Intel CPU

  2. 多模态模型支持

  3. 推测解码:对不同算法的广泛支持

    对于 Speculative Decoding 的中译采用这篇综述的选择

  4. 自动前缀缓存

  5. 结构化的输出(JSON、regex、grammar)

第三次(2024.04.02)

总览

这部分和第一次 Meetup 也差不多。

总结了特征

项目进展

自上一次 Meetup(间隔 62 天)之后的更新,也就是 2 月和 3 月的进展。

  1. 模型支持:支持更多的模型架构;开始支持视觉语言模型:LLaVa

  2. 硬件支持:对 AMD 和 AWS Neuron 更好的支持;初步支持 Intel CPU;原型支持 Intel GPU 和 Intel Habana Gaudi

  3. 特性:

    1. 自动前缀缓存:有两个例子:多轮对话和共享系统 prompt
    2. 引导式解码:支持通过内容大纲、正则表达式、JSON 等,兼容 OpenAI
    3. 性能优化
      • MoE 内核优化
      • 在量化中集成 Marlin 内核
      • 推测解码:小规模模型生成初稿。未来会支持其他方法:ngram,RAG,…
      • 代码重构:Attention 后端(目的是可以为不同硬件和模型轻松插入不同的 attention 实现);模型执行器(目的是可以简单地加入新硬件支持并且把代码和硬件架构分离)
      • 开源社区的快速发展

未来计划

高层次目标

  1. 广泛的模型支持:Encoder-decoder 模型(T5, Whisper, bge);混合架构(Jamba);更多视觉模型

  2. 出色的硬件支持:持续支持和积极协作的硬件有

    • GPUs: NVIDIA, AMD, Intel GPU
    • Tensor Accelerators: Google TPU, AWS Inferentia, Habana Gaudi
    • CPU: Intel/AMD CPU
  3. 生产级别的引擎

    • 推测解码框架:添加多种算法;支持自定义;探索 Medusa/Eagle
    • 分块预填充度器
    • 功能质量提升(Quality of Life Features):更快的模型加载;更好的指标和日志;API 服务器性能
  4. 性能优化:

    • 通过 FlashInfer 和 OpenAI Triton 提升内核性能
    • 量化:FP8 格式支持;通过 Marlin 内核改进仅权重量化;激活值量化框架(W8A8, FP8 等)
    • 引导式解码优化
  5. 可扩展架构

    • 原型流水线并行
    • 可扩展内存管理器
    • 可扩展调度器
    • torch.compile 调研
  6. 强大的开源社区支持

    • 持续的基准测试(急切需要资源!)
    • nightly 安装包和 Docker 镜像
    • 承诺每两周发布一次

剩余的 PPT 内容是 Roblox 的在线服务性能基准测试。

第四次(2024.06.11)

vLLM 简介

还是和之前的差不多,这里再放一张新图,详细地列举了已使用的推理优化技术。

项目进展

自上一次 Meetup(间隔 70 天)之后的更新

  1. 广泛的模型支持:Deepseek MoE、Gema、StarCoder2、Qwen2 MoE 等等

  2. OpenAI API 兼容性:添加嵌入式 API;支持 OpenAI 批处理文件格式;对 tool_use 的初始支持

  3. OpenAI Vision API 兼容性:围绕多模态模型的基础设施进行广泛的重构,以改善用户和开发人员的体验;与 OpenAI Vision API 的端到端服务兼容性

  4. 多样化的硬件支持:

    • 已经支持:NVIDIA GPU、AMD GPU、AWS Neuron、x86 CPU
    • 正在开发:Intel GPU、Google TPU、Intel Gaudi
  5. 功能亮点(已准备好测试和投入生产使用,并且会在之后的版本中默认启用):

    • 分块预填充:以首个 token 产生时间为代价换取 token 间延迟(第一个 token 变慢,但整体更流畅)
    • FP8 量化:以一定的精度为代价换取更低的延迟。
    • 前缀缓存:以更高的内存占用为代价换取更低的延迟。
    • 推测解码:以更高的计算成本为代价换取更低的延迟。
  6. 持续优化

    • SOTA 内核:集成 FlashAttention 和 FlashInfer
    • GPU 通信:NCCL,自定义 allreduce,用于分布式推理
    • 更好的架构:基于多进程的 GPU 执行器
  7. 其他提升

    • 易用性:集中管理并文档化的环境变量
    • 持续的性能优化:
      • 减少每步调度的开销
      • 自动前缀缓存优化
      • 内核调优

未来计划

主线内容和第四次 Meetup 的差不多,分别是

  • 广泛的模型支持
  • 出色的硬件支持
  • 生产级别的引擎
  • 性能优化:
  • 可扩展架构
  • 强大的开源社区支持

有一张图进行总结

推测解码深入解析

这里推荐一篇综述:LLM 推理加速新范式!推测解码(Speculative Decoding)最新综述,PPT 中的内容就是简要介绍一下推测解码,在 vllm 中的应用与优化。

第五次(2024.07.24)

vLLM 简介

与第四次相同

项目进展

自上一次 Meetup(间隔 43 天)之后的更新

  1. Llama 3.1:与 Llama 3.1 合作,第一时间支持所有 Llama 3.1 模型,并给出了多样的选择来运行 Llama 3.1 405B,详情可见 博客

  2. 新模型

    • 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
  3. 多样化的量化方法:W4A16、W8A16 等等。最新的支持可以看这里的表格。

  4. CPU 卸载(v0.5.3 更新):只卸载模型权重,具有更低的执行时间。

  5. 流水线并行:从 v0.5.1 开始支持。

  6. 推测解码:支持 Medusa 和 MLP 推测器

  7. TPU 硬件支持

  8. 详细的性能指标和比较,可见 https://perf.vllm.ai/

  9. 开发体验:新的 CLI(vllm {serve, chat, complete});在 A100 和 H100 上加强的测试框架;发布优化

未来计划

只贴了一张现在的完成图,未来应该还是这几个方向

流水线并行深入解析

很奇怪,后续 PPT 没有内容了。这次 Meetup 的 PPT 页数只有 28 页。

第六次(2024.09.09)

vLLM 简介

与第四次相同

项目进展

自上一次 Meetup(间隔 47 天)之后的更新

  1. 有关 Llama 3.1 的内容和第五次相同

  2. 新模型

    • 新 LLM:Nemotron models (Nemotron-3, Nemotron-4, Minitron)、Granite、Phi3.5 MoE、Jamba 1.5
    • 新模型架构组件:Encoder decoder baselines;Native SSM baselines
  3. 多模态更新

    • 特征
      • 新多模态:语音(UltravoxModel from fixie.ai)
      • 多图片接口,以 Phi-3.5-vision-instruct 为例
      • 除了 PIL 图像外,还支持图像嵌入作为输入
    • 优化
      • 通过张量并行的移植实现为 ViT(CLIP、SigLIP)节省了内存
    • 模型支持扩展
      • 新 VLM:InternVL2, BLIP-2, MiniCPM-V
      • 共计支持 11 个 LMM
    • 即将到来
      • 支持具有动态帧数的视频多模态
      • 支持 Qwen2-VL
  4. 量化更新

    • 新格式:gguf,bitsandbytes,qqq (w4a8)
    • 新推理内核:awq_marlin
    • 推出 LLM Compressor,用于生成带有量化权重、激活值和键值缓存的模型。
  5. 性能提升

    • 一系列增强措施,将吞吐量提高两倍。主要有
      • 服务和引擎进程的分离(单个进程变成独立的两个进程)
      • 多步调度(一次调度后可以运行多次 forward)
      • 异步输出处理(输出和 forward 重叠)
    • 聚焦于保持 GPU 高效运转并减少 CPU 开销
    • 性能依然是首要任务
    • Cody 将深入讲解每种技术!(应该是指后面的性能深入解析)
  6. 其他提升

    • 对 python 对象进行缓存来减少分配
    • 非阻塞的 CPU-GPU 间通信
    • 为简单的采样参数提供快速路径

未来计划

Q3 Roadmap 图和第五次相比只多完成了 Model Support 中的 Encoder-decoder

  1. torch.compile

    • TPU 后端已经将 torch.compile 集成为始终可用的核心功能
    • 但 CUDA 后端仍不稳定,正在与 PyTorch 团队积极合作
    • 目标是始终启用 torch.compile,同时自动决定使用哪些组件,比如零开销的 Dynamo 和 Inductor
  2. KV Cache 传输

    • 为什么选择 KV 传输:因为这是一种无痛添加新功能的方式

      • 分离的预填充
      • 连接(多个)vLLM 到 KV 缓存数据库(例如 Redis 数据库)
    • 提供了两个 API 在 KV 生产者进程和 KV 消费者进程之间传输 KV,在此不具体讲,可以简单看一下图

      1
      2
      
      buffer(tokens, roi, key, value) → None
      drop_select(tokens, roi) → Optional[tokens, roi, key, value]
      

  3. 重构 vLLM 以获得更干净的内核

    • 总体目标:最小化 GPU 空闲时间和简化代码
    • 异步调度:异步输出处理和多步调度的推广/简化
    • 前缀集中缓存的设计(Prefix caching-centric design):默认启用前缀缓存;使用它来优化并行采样和重计算;使用 cascade inference 内核
  4. 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 中比较简单,只是罗列了一下。(具体内容还得靠讲)

  1. 模型支持

    • 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)
  2. 硬件支持

    • NVIDIA GPU
    • AMD GPU
    • AWS Neuron
    • Intel CPU/GPU
    • Google TPU
    • Intel Gaudi
  3. 模型性能

    • 深度优化至 CUDA 内核级
    • 多功能 CUDA 图支持
    • 广泛支持量化方法
    • 最先进的量化内核
  4. 引擎特征

    • 分块预填充
    • 推测解码
    • 自动前缀缓存
    • 多 LoRA 服务
    • 结构化输出
    • 可观测性
  5. 分布式系统架构

    • 张量并行
    • 流水线并行
    • CPU 卸载
    • 自定义 All-Reduce
    • 异步张量并行和 Flux 矩阵乘法内核
  6. 开源社区情况

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
  • 增量输入准备(连续批处理)

    • 在 V0 中,输入张量在每个 step 都从头开始重新创建
    • 在 V1 中,输入张量被缓存,每个 step 中只修改不同的地方
  • 分段 CUDA 图

    • V0:将整个模型捕捉到 CUDA 图中
      • 优点:模型执行时几乎没有 CPU 开销
      • 缺点:模型必须是静态的,且不能包含 CPU 操作
    • V1:混合方法
      • 在 Eager 模式的 PyTorch 中执行注意力操作,提供完全的灵活性
      • 对其他操作使用 CUDA 图,避免大部分 CPU 开销
  • 增强的 API 服务器

    • 使用后台忙循环(busy loop)作为主要执行循环
      • 确保引擎不会因为等待 API 服务器而暂停
    • 将解码器放在单独的进程中
      • 解码过程不属于关键路径
      • 如果解码器检测到停止字符串,它会向引擎发送中止信号(总体过程是异步)
  • 更高效的前缀缓存

    • 在 V0 中,前缀缓存导致了较高的 CPU 开销
      • LRU 驱逐器在每次块分配时需要花费 O(N) 时间,其中 N 是空闲块的数量。
    • 在 V1 中使用了更高效的数据结构
      • 使用双向链表和字典,实现 O(1) 时间的块分配
      • 初始化后不再创建新的 python 对象
      • 即使缓存命中率为 0%,其性能下降也仅为 0-1%
  • VLMs 的细粒度调度

    • 引入嵌入式缓存以解耦视觉编码器和 LLM 解码器
      • 视觉编码器将输出存储到嵌入缓存中
      • 语言模型从嵌入缓存中获取 “soft token”
    • 分别调度视觉编码器和 LLM 解码器
      • 引入了编码器预算(encoder budget),以避免在同一步骤中处理太多图像(限制了每一步的延迟)
      • 调度器精确地跟踪输入之间的依赖关系,并考虑利用它们进行调度决策
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 行新代码,可以看到发展得非常快。


本站不记录浏览量,但如果您觉得本内容有帮助,请点个小红心,让我知道您的喜欢。