前言
vLLM 是一个专为大语言模型(LLM) 设计的高吞吐量、内存高效的推理和服务引擎。它由加州大学伯克利分校的研究人员开发,并迅速成为业界部署LLM服务的首选工具之一。
用更少的硬件,更快、更便宜地服务更多的用户。
认识
核心问题:传统服务方式的瓶颈
在 vLLM 出现之前,服务LLM(如 GPT、LLaMA 等)面临几个主要挑战:
巨大的内存占用:LLM 参数量巨大(从7B到千亿级),仅模型权重就需要消耗大量 GPU 内存。
内存浪费(Key-Value Cache 问题):LLM 推理是自回归的,每次生成一个 token。为了加速生成过程,系统会缓存之前所有生成步骤的中间计算结果(称为 Key-Value Cache 或 KV Cache)。
问题在于:系统通常会为每个请求的最大可能长度预先分配 KV Cache 内存。但由于请求的输入和输出长度变化巨大,这会导致大量内存被分配但未被使用,内存利用率极低(论文中指出可能低至 20%)。这是性能的主要瓶颈。
低吞吐量:低下的内存利用率意味着单个 GPU 能够同时处理的请求数量(并发度)非常有限,导致总体吞吐量(Tokens/Second)不高,服务成本高昂。
vLLM 的杀手锏:PagedAttention
vLLM 的核心创新是一个受操作系统虚拟内存和分页概念启发的算法——PagedAttention。
传统方式(连续内存分配):
就像早期的电脑程序,必须申请一整块连续的内存空间才能运行。如果程序很大但内存碎片多,即使总空闲内存够用,也可能无法分配。
PagedAttention(分页式管理):
它巧妙地将每个请求的 KV Cache 划分为固定大小的“块”(Blocks),类似于操作系统中的“内存页”。
物理块:GPU 上实际的、固定大小的 KV Cache 存储空间池。
逻辑块:每个请求看到的自己独有的、连续的 KV Cache 空间视图。
工作原理
当处理一个序列时,vLLM 不再预先分配一大片连续内存,而是按需从全局的“物理块”池中申请空闲块。
一个序列的 KV Cache 可能被分散存储在许多个非连续的物理块中。
PagedAttention 内核知道如何根据“块表”(类似于页表)来高效地找到并组装这些分散的块,以便正确地进行注意力计算。
优势
近乎零浪费的内存使用:内存以块为单位分配,几乎没有内部碎片。这使得 GPU 可以容纳比传统方式多得多的序列(提高了 2-4 倍的吞吐量)。
高效的内存共享:这在处理高级解码方法时非常强大,例如:
并行采样(n > 1):生成多个候选输出时,它们可以共享提示词(Prompt)的 KV Cache 块。
波束搜索(Beam Search):不同的波束可以共享共同的历史轨迹的块。
这种共享是写时复制(Copy-on-Write) 的,进一步极大地节省了内存。
使用
方式一:离线批量推理
1 | from vllm import LLM, SamplingParams |
方式二:启动在线API服务
启动服务器(命令行)1
2
3python -m vllm.entrypoints.api_server \
--model meta-llama/Llama-2-7b-chat-hf \
--served-model-name llama-2-7b-chat
像调用 OpenAI 一样调用它1
2
3
4
5
6
7
8curl http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "llama-2-7b-chat",
"prompt": "San Francisco is a",
"max_tokens": 128,
"temperature": 0
}'
reference
vLLM仓库: https://github.com/vllm-project/vllm
vLLM文档: https://docs.vllm.ai/en/latest/serving/openai_compatible_server.html
BentoML文档: https://docs.bentoml.com/en/latest/get-started/introduction.html
AutoAWQ仓库: https://github.com/casper-hansen/AutoAWQ
AutoGPTQ仓库: https://github.com/AutoGPTQ/AutoGPTQ
SqueezeLLM仓库: https://github.com/SqueezeAILab/SqueezeLLM?tab=readme-ov-file
Locust文档: https://docs.locust.io/en/stable/index.html
KVQuant仓库: https://github.com/SqueezeAILab/KVQuant
LLMCompiler仓库: https://github.com/SqueezeAILab/LLMCompiler
ChatGLM3量化: https://hf-mirror.com/THUDM/chatglm3-6b/blob/main/quantization.py
使用chatglm.cpp量化: https://github.com/uppercaveman/chatglm3-6b-model-quantization
HF BitsAndBytes: https://huggingface.co/docs/bitsandbytes/index
HF量化文档: https://huggingface.co/docs/transformers/quantization
HF加入新量化方法: https://huggingface.co/docs/transformers/hf_quantizer
HF quanto: https://github.com/huggingface/quanto
ALQW量化: https://github.com/Vahe1994/AQLM
ALQW论文: https://arxiv.org/pdf/2401.06118
llm-awq: https://github.com/mit-han-lab/llm-awq
autoawq: https://github.com/mit-han-lab/llm-awq
QLoRA: https://huggingface.co/papers/2305.14314
EETQ: https://github.com/NetEase-FuXi/EETQ
AutoAWQ教程: https://colab.research.google.com/drive/1HzZH89yAXJaZgwJDhQj9LqSBux932BvY#scrollTo=WE9IhcVyktah
GPTQ量化Llama3: https://mp.weixin.qq.com/s/2-bAKn6eAeEG2JxCTbczOw
ggml仓库: https://github.com/philpax/ggml
SqueezeLLM量化: https://github.com/SqueezeAILab