vLLM
目前最主流的大模型推理部署框架 vLLM,核心创新是 PagedAttention,借鉴操作系统虚拟内存分页思想管理 KV Cache。
PagedAttention:把 KV Cache 切成固定大小的“页”,按需分配,彻底消除显存碎片,并发请求共享 KV Cache 成为可能。Continuous Batching(连续批处理):不等一批请求全部完成再处理下一批,而是动态插入新请求,GPU 利用率从 30% 提升到 90%+。Prefix Caching:相同前缀(如 System Prompt)的 KV Cache 自动复用,多轮对话场景首 token 延迟大幅降低。Speculative Decoding(投机采样):用小模型草稿 + 大模型验证,在不损失精度的前提下提升生成速度。支持 OpenAI 兼容 API,一行命令启动,已成为企业私有化部署的事实标准。
介绍
vLLM(Vectorized Large Language Model Serving System)是加州大学伯克利分校团队推出的开源推理系统,突破大模型部署中显存利用率低与推理吞吐量受限的双重挑战
Meta 前 PyTorch 团队推出 vLLM,最大特色“PagedAttention”。
两项核心机制:PagedAttention(分页注意力)与Continuous Batching(连续批处理),二者均受操作系统内存分页机制启发,重构了注意力计算与请求调度的底层逻辑,从而在不牺牲精度的前提下,大幅优化了显存管理效率与并发推理能力。
- PagedAttention:受操作系统分页管理机制启发,将注意力机制中的键值缓存(KV Cache)以非连续方式部署于显存中。相较传统框架为每个请求强制分配连续显存块的模式,vLLM 将 KV Cache 拆分为固定尺寸的“页”,实现显存空间的动态调度与高效复用,从而彻底缓解了显存碎片化、预留冗余与并发容量受限三大核心痛点。该架构使显存利用率由传统方案的 60% 显著跃升至 95% 以上,显著增强系统对高并发请求的承载能力。
- PagedAttention:KV 缓存被划分为块;块在内存空间中不需要连续
- Continuous Batching:突破传统批量等待机制,支持新请求实时插入处理队列,实现GPU资源的零空闲运行。该机制显著降低高并发场景下的TTFT(首字出词时间),在Llama3.1-170B-FP8单H100环境下,TTFT低至123ms,优于TensorRT-LLM(194ms)与SGLang(340ms)。
多卡并行优化:全面兼容张量并行(Tensor Parallelism)与流水线并行(Pipeline Parallelism),依托NCCL/MPI等高性能通信框架,实现模型参数的精细化切分与高效同步,在降低显存占用的同时,显著增强整体吞吐能力。
量化优化支持:原生集成GPTQ、AWQ等先进量化算法,精准压缩模型参数规模,大幅提升GPU计算密度与推理效率,实现性能与资源消耗的最优平衡。
【2025-12-13】DeepSeek倒逼vLLM升级!芯片内卷、MoE横扫千模,vLLM核心维护者独家回应:如何凭PyTorch坐稳推理“铁王座”
2023 年, 加州大学伯克利分校 Sky Computing Lab 学生与研究员开源核心的 PagedAttention 技术,vLLM
短短一年多, GitHub Star 数突破 4 万,并迅速增长至如今的 6.5 万,如今已成为全球科技公司首选的推理引擎。
2024 年 11 月,红帽正式收购 Neural Magic,并将包括 vLLM 核心维护者 Michael Goin 在内的核心团队纳入旗下。
vLLM(Very Large Language Model)专为大语言模型(LLM)优化的高效推理框架
其核心:PagedAttention、动态批处理pd并行、多LoRA动态加载等
PagedAttention 本质是灵活管理 KV Cache(注意力缓存)的方式。
- 传统 transformer 推理时,每个 token 都带上历史上下文,缓存爆炸。
- vLLM 通过类似虚拟内存分页方式,优化性能。像会打麻将的高效服务员,记牌记得巨快
好处
- API 设计接近 OpenAI 标准接口,部署友好,尤其对做“OpenAI替代”的场景特别合适。
- 高并发时不掉链子,响应速度几乎线性增长。
前提:GPU A100 起步。
vllm vs sglang
【2025-09-27】vllm:pd并行、多LoRA动态加载
vllm和sglang 部署分别:
- vLLM 在高并发和低延迟场景下表现优异,尤其擅长快速生成第一个词(TTFT低)。
- SGLang 在多轮对话这类前缀复用率高的场景中,吞吐量优势明显,测试显示其在Llama-7B上的吞吐量可比vLLM高5倍。
问题
vllm 显存不够
启动本地模型
vllm serve /ofs/ese-llm-ssd/models/Qwen3-4B-Instruct-2507
# 修改:降低 max_model_len
vllm serve /ofs/ese-llm-ssd/models/Qwen3-4B-Instruct-2507 --port 8010 --host 0.0.0.0 --max_model_len 230000
报错
- 加载模型最大序列长度(262144)需要 36.0 GiB KV cache, 当前只有 32.31 GiB
- 提示:① 降低序列长度
max_model_len② 提升 GPU 使用率gpu_memory_utilization(默认已用90%)
ValueError: To serve at least one request with the models's max seq len (262144), (36.0 GiB KV cache is needed, which is larger than the available KV cache memory (32.31 GiB). Based on the available memory, the estimated maximum model length is 235264. Try increasing `gpu_memory_utilization` or decreasing `max_model_len` when initializing the engine. See https://docs.vllm.ai/en/latest/configuration/conserving_memory/ for more details.
vllm 默认占满显存
【2026-3-26】案例
- vllm 加载 qwen-7b 模型,显存占到40G左右,但关掉vllm时占用17G
- vllm 加载 qwen3-4b 模型,A6000,显存占41G!
显存计算公式:
- 显存占用 ≈ KV Cache + 模型参数 + 激活值 + 临时buffer
$ [ \text{显存占用} \approx \text{KV Cache} + \text{模型参数} + \text{激活值} + \text{临时 buffer}] $
详见站内专题:GPU显存分析
gpu_memory_utilization 默认值为 0.9,GPU 内存使用率为 90%。如果遇到显存不足的问题,可以降低该值。
- KV 缓存:在自回归解码过程中,LLM 的所有输入标记会生成注意键和值张量,并保存在 GPU 内存中,这些缓存可能会占用大量显存。
- vLLM 引入 PagedAttention 来有效管理 KV 缓存,这种机制允许在不连续内存空间中存储连续的键和值。
通过合理调整 gpu_memory_utilization 参数,可以在保证模型性能的同时,优化显存的使用。
调用代码
import vllm
model = vllm.LLM(
model_path="/data/models/Meta-Llama-3-8B-Instruct",
tensor_parallel_size=2,
gpu_memory_utilization=0.15, # 设置显存利用率为 15%
temperature=0.2,
top_p=0.95,
max_tokens=100
)
vllm 不支持 embedding的lora
【2025-2-4】vllm 不支持 embedding的lora功能!
It’s not supported yet according to the compatibility matrix. Let me update the supported models page to avoid this confusion. cc @jeejeelee
undefined symbol
【2026-4-7】错误信息
import vllm._C # noqa
^^^^^^^^^^^^^^
ImportError: /ofs/ese-llm-ssd/users/wangqiwen/envs/py312/lib/python3.12/site-packages/vllm/_C.abi3.so: undefined symbol: _ZN3c104cuda29c10_cuda_check_implementationEiPKcS2_ib
分析
- 豆包:vllm 与 PyTorch/CUDA 版本不兼容
解法
- 查看 pytorch、cuda和vllm版本
- 对照 vllm 官方要求(关键):
- vllm 0.4.x+ 需 PyTorch ≥ 2.0.0,CUDA ≥ 11.8
- vllm 0.3.x 需 PyTorch ≥ 1.13.0,CUDA ≥ 11.7
- 升级对应版本
# 查看当前 PyTorch 版本:
python -c "import torch; print(torch.__version__); print(torch.version.cuda)"
# 查看当前 vllm 版本:
uv pip list | grep vllm
# 升级vllm: 0.16 -> 0.19
uv pip install vllm --upgrade
vLLM 框架
核心架构是LLMEngine:包含调度器(Scheduler)和推理工作器(Worker)
- 调度器(Scheduler):
- 调度策略(policy):
- 请求的连续批处理(Continuous Batching)
- 请求队列维护:waiting(待处理)、running(正在处理)、swapped(因显存不足被挂起)
- 空间“调度指挥官”(BlockSpaceManager):负责逻辑资源规划与分配策略;
- 计算kv cache需要的块数量
- 判断是否需要为新token分配新的空间(如需则通知cacheengine)
- 内存共享:例如在并行采样时,多个输出序列可共享同一prompt的KV缓存块
- 调度策略(policy):
- 推理工作器(Worker):
- 模型运行:包括多GPU分布式计算(张量并行、流水线并行)
- 空间“后勤执行者”(CacheEngine):负责物理显存的具体操作与数据存取。
- 性能效果:
- 吞吐:提升高达24倍
- 耗时:提升1.2倍。
如何加载本地模型?
- (1)使用绝对路径,而不是 模型名 —— 系统不再从hf上下载
- (2)加参数
本地模型
vllm默认从远程(huggingface或modelscope)加载模型
那么,如何加载本地模型?
- (1)使用绝对路径(含模型名)
- (2)加全局变量
bash 模式
vllm serve ~/model/qwen
TRANSFORMERS_OFFLINE=1 vllm serve
模版
from vllm import LLM, SamplingParams
# ========== 只需要改这里 ==========
MODEL_PATH = "/你的/本地/模型/路径"
GPU_COUNT = 1
# =================================
llm = LLM(
model=MODEL_PATH,
tensor_parallel_size=GPU_COUNT,
trust_remote_code=True,
gpu_memory_utilization=0.85
)
sampling_params = SamplingParams(
temperature=0.1,
max_tokens=2048
)
prompt = "你好"
output = llm.generate(prompt, sampling_params)
print(output[0].outputs[0].text)
多 LoRA 动态加载
- 无延迟切换:单基础模型(如Llama 3-8B)同时挂载多个LoRA适配器(如聊天/函数调用),请求时通过lora_request参数指定,切换延迟低于1ms。
- 资源复用:基础模型参数仅加载一次,适配器共享显存,支持5+适配器并行服务。
与stable diffusion类似,vllm 也支持在请求调用时指定调用某个lora;但有两点差异:
- vllm中的lora是一开始全部就加载进模型的,(sd是请求时才加载)
- vllm中每次请求只能指定一个lora
# 同时加载两个适配器
vllm serve meta-llama/Meta-Llama-3-8B \
--enable-lora \
--lora-modules \
oasst=/path/to/oasst_adapter \ # 名称 oasst
xlam=/path/to/xlam_adapter # 名称 xlam
PagedAttention 动态分页机制
分页注意力机制(PagedAttention)是什么?
- 分页注意力机制借鉴了计算机操作系统中的内存分页管理,通过动态分配和复用显存空间,显著提升大模型推理的效率和吞吐量。
传统大模型推理中,注意力机制(Transformer的自注意力层)为每个请求序列分配连续的显存块,存储以下数据:
- (1)键值缓存(Key-Value Cache,KV Cache):存储历史token的键值对,用于生成后续token。
- (2)中间激活值:计算注意力权重时的中间结果。
vLLM基于PyTorch构建,创新性地引入了PagedAttention技术。借鉴操作系统的虚拟内存分页机制,将注意力键值对(KV Cache)存储在非连续显存空间,显著提高了显存利用率。
PagedAttention 通过分块管理显存、动态按需分配和跨请求共享内存,解决了传统方法中显存碎片化、预留浪费和并发限制三大瓶颈。
特点
- 分块管理KV缓存:将注意力键值(Key-Value Cache)划分为固定大小的块(如4-16 tokens/块),按需动态分配GPU显存,避免传统连续分配导致的碎片问题。
- 显存复用与共享:短序列推理时仅占用必要块,释放空间供其他请求使用;支持跨请求的缓存共享(如相同前缀提示词),显存利用率提升最高达25%。
- 写时复制(Copy-on-Write):共享块标记为只读,修改时创建新副本,减少重复计算
vllm 部署
安装
# 安装基础版本
pip install vllm
# 安装支持CUDA的版本
# pip install vllm-nightly # 无效,报错
pip install -U vllm \
--torch-backend=auto \
--extra-index-url https://wheels.vllm.ai/nightly
vllm 两种模型部署方式:
- 在线服务形式(Online Serving)
- 在线服务: 通过指令启动vllm服务,将模型以服务的形式完成部署,之后可以通过openai格式的api来访问模型
- 离线推理形式 (Offline Inference)
- 离线推理: 通过类方式初始化一个模型,之后传入提示词即可访问模型
vllm 使用
启动服务后,网页访问地址 redoc 显示可用的 get/post 方法
bash 启动
实测
# [2026-4-16] luban 上加载本地模型,A6000(45G)
vllm serve /ofs/ese-llm-ssd/models/Qwen3-4B-Instruct-2507 # 报错,显存超出
# 修改:降低 max_model_len
vllm serve /ofs/ese-llm-ssd/models/Qwen3-4B-Instruct-2507 --port 8010 --host 0.0.0.0 --max_model_len 230000
# 加上token api
vllm serve /ofs/ese-llm-ssd/models/Qwen3-4B-Instruct-2507 --port 8010 --host 0.0.0.0 --max_model_len 230000 --api-key token_luban_wqw
# 【2026-4-16】模版
model_path="/ofs/ese-llm-ssd/models/Qwen3-4B-Instruct-2507"
token_path="token_luban_wqw"
gpu_memory_utilization=0.9 # 默认
CUDA_VISIBLE_DEVICES=0 vllm serve $model_path --tokenizer $token_path \
--trust-remote-code --dtype auto \
--tensor-parallel-size 1 --gpu-memory-utilization $gpu_memory_utilization \
--port 8070
启动服务后,网页访问地址 redoc 显示可用的 get/post 方法
调用模型
此时,可以调用模型
【2026-4-16】实测
注意:
- 模型路径要完整,使用本地绝对路径!
- 如果设置了key,请务必添加认证信息 (token_luban_wqw)
- 如果有代理,请关闭!
# 关闭代理
# unset http_proxy unset all_proxy
# (1) 快速验证服务是否正常:查看当前模型
curl --location 'http://10.191.61.23:8010/v1/models' \
--header 'Authorization: Bearer token_luban_wqw'
# (2) 续写模式:completions, 对应 prompt 参数
curl http://10.191.61.23:8010/v1/completions \
-H "Content-Type: application/json" \
-H 'Authorization: Bearer token_luban_wqw' \
-d '{
"model": "/ofs/ese-llm-ssd/models/Qwen3-4B-Instruct-2507",
"prompt": "San Francisco is a",
"max_tokens": 20000,
"temperature": 0
}'
# (3) chat 模式: chat/completions, 对应 messaages 参数
curl -X POST "http://10.191.61.23:8010/v1/chat/completions" \
-H "Authorization: Bearer token_luban_wqw" \
-H "Content-Type: application/json" \
-d '{
"model": "/ofs/ese-llm-ssd/models/Qwen3-4B-Instruct-2507",
"messages": [
{"role": "user", "content": "你好,世界!"}
],
"max_tokens": 100,
"temperature": 0.7
}'
# 或
curl --location 'http://10.191.61.23:8010/v1/chat/completions' \
--header 'Authorization: Bearer token_luban_wqw' \
--header 'Content-Type: application/json' \
--data '{
"model": "/ofs/ese-llm-ssd/models/Qwen3-4B-Instruct-2507",
"messages": [
{
"role": "system",
"content": "你是一个滴滴出行的智能客服"
},
{
"role": "user",
"content": "如何拉黑拼友"
}
],
"n": 1,
"temperature": 1.0,
"top_p": 0.8,
"add_generation_prompt": true,
"do_sample": false,
"best_of": 5,
"use_beam_search": true,
"max_tokens": 1000,
"skip_special_tokens": false,
"enable_thinking": false
}'
代码启动
# 示例代码:生成文本
from vllm import LLM, SamplingParams
prompts = ["什么是vLLM?", "vLLM的优势是什么?"]
sampling_params = SamplingParams(temperature=0.8, top_p=0.95)
llm = LLM(model="meta-llama/Llama-2-7b-chat-hf") # 可限制最大并发:max_num_seqs=2,使用FP16:dtype="float16"
outputs = llm.generate(prompts, sampling_params) # 批量推理
for output in outputs:
print(f"输入:{output.prompt}\n输出:{output.outputs[0].text}\n"2
【2026-4-16】实测:代码调用模型
from openai import OpenAI
url = "http://10.191.61.23:8010"
model_path = "/ofs/ese-llm-ssd/models"
model_name = "Qwen3-4B-Instruct-2507"
token = "token_luban_wqw"
client = OpenAI(
base_url = f"{url}/v1",
# base_url="http://localhost:8000/v1",
api_key = token,
)
# chat 模式
completion = client.chat.completions.create(
model = f'{model_path}/{model_name}',
# model="NousResearch/Meta-Llama-3-8B-Instruct",
messages=[
{"role": "user", "content": "Hello!"}
]
)
print(completion.choices[0].message)
参数解释
服务开启和各参数作用
vllm 服务启动指令如下
vllm serve deepseek-ai/deepseek-vl2-tiny \
--hf_overrides '{"architectures": ["DeepseekVLV2ForCausalLM"]}' \
--dtype float16 --trust_remote_code \
--host 0.0.0.0 --port 8080 \
--chat_template template_deepseek_vl2.jinja \
--gpu-memory-utilization 0.7 \
--limit-mm-per-prompt "image=8"
详见地址
bert 模型
除了生成式任务,但分类任务同样可以通过指定合适的任务类型实现。
【2025-5-1】vLLM项目中部署BERT
关键启动参数包括:
python -m vllm.entrypoints.api_server \
--model path/to/bert_model \
--tensor-parallel-size 1 \
--dtype float16 \
--max-model-len 512 \
--served-model-name bert-cls
注意:
- 最大序列长度应设置为BERT标准配置(通常512)
- 半精度(float16)可显著提升推理速度
- 服务名称用于后续API调用标识
分类任务可以采用以下调用方式:
import openai
client = openai.Client(base_url="http://localhost:8000/v1")
response = client.completions.create(
model="bert-cls",
prompt="这是一条需要分类的文本",
max_tokens=1, # 分类任务通常只需要1个token输出
temperature=0 # 确保确定性输出
)
性能优化建议
- 批处理优化:通过增大
--max-batch-size参数提高吞吐量 - 量化部署:尝试使用
--quantization bitsandbytes进行8bit量化 - 请求合并:客户端实现请求队列合并,减少小包传输
- 监控集成:添加Prometheus监控指标采集
vLLM 分布式
资料
- 【2025-09-07】利用 vLLM 进行 rollout
- 【2025-11-30】vLLM & Ray 分布式部署Qwen2.5-14B模型
- 【2025-12-17】vLLM MoE 调优手册(上篇):TP、DP、PP 与 Expert Parallelism 实战指南
更多分布式计算知识,见站内专题:分布式训练理论
vLLM 并行方式
vLLM 并行方式:
- Tensor Parallelism(TP,张量并行):每个gpu只存权重的1/n, 计算完成后都要AllReduce同步
- Data Parallelism(DP,数据并行)
- Pipeline Parallelism(PP,流水线并行)
- Expert Parallelism(EP,专家并行,MoE 专用开关)
vLLM 允许设置 PP 和 DP
问题:
- TP 如何切分权重、为何需要 AllReduce
- DP+EP 在 MoE 场景下如何配合 AllToAll 做请求级并行
- 为什么所谓的“DP Attention” 和传统数据并行完全不是一回事
- 什么时候要开
--enable-expert-parallel,什么时候反而是徒增开销
「交叉点」:
- TP+EP:低并发、交互式场景下延迟更优
- DP+EP:高并发、大吞吐场景下扩展性更好
专家激活密度(每个 token 实际激活多少 expert)会直接决定 EP 是加速还是减速;而像 DeepSeek 这种 MLA/MQA 模型,在 KV cache 管理上又需要特别对待。
DP
命令
vllm serve model-name --data-parallel-size 4
TP
vllm 部署 Qwen 2.5 14B 模型
下载模型
huggingface-cli download Qwen/Qwen2.5-14B –resume-download –local-dir /data/models/qwen2.5-14b
查看模型的参数:
cat /data/models/qwen2.5-14b/config.json
vllm 部署模型时要设置 tensor-parallel-size 和 pipeline-parallel-size 两个参数,和模型结构、GPU设备数量都有关系
- 参数涉及到模型并行的两种方式 Tensor Parallelism (TP,
张量并行)和Pipeline Parallelism (PP,流水线并行)
只采用 Tensor Parallelism,不采用 Pipeline Parallelism。
从config.json中 可以知道注意力头的数量 “num_attention_heads”是 40
- num_attention_heads 必须是 tensor-parallel-size 张量并行度的整数倍。
vllm 部署命令:
vllm serve model-name --tensor-parallel-size 4
关闭 NCCL,使用 ray
export NCCL_IB_DISABLE=1
export NCCL_SOCKET_IFNAME=eth0
export NCCL_DEBUG=INFO
python -m vllm.entrypoints.openai.api_server \
--model /data/models/qwen2.5-14b \
--tensor-parallel-size 4 \
--pipeline-parallel-size 1 \
--trust-remote-code \
--gpu-memory-utilization 0.75 \
--max-num-seqs 64 \
--max-model-len 4096 \
--host 0.0.0.0 \
--port 8000 \
--distributed-executor-backend=ray
测试验证
另起终端界面,运行以下命令,测试模型是否可用
curl http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{"model": "/data/models/qwen2.5-14b","max_tokens":"256" ,"temperature": "0.7","prompt": "请介绍一下你自己?"}' | jq
PP
把模型的不同层拆给不同 GPU / 节点,每块 GPU 负责一段「流水线阶段」,数据像装配线一样一级一级往后传
vLLM 不会傻傻地让流水线一次只跑一个请求,而是同时塞进多条请求:
- GPU 0 处理请求 B 的第 1 段
- GPU 1 同时处理请求 A 的第 2 段
- GPU 2 可能在处理更早一条请求的第 3 段
这样流水线各阶段都能被填满,大幅减少 pipeline bubble。
示例
# Pure PP: 4 GPUs as 4 pipeline stages
vllm serve model-name --pipeline-parallel-size 4
# TP within nodes + PP across nodes (2 pipeline stages with each pipeline has 4 GPUs)
vllm serve model-name --tensor-parallel-size 4 --pipeline-parallel-size 2
或
llm = LLM(
model=str(model_dir),
dtype='bfloat16',
gpu_memory_utilization=0.4,
tensor_parallel_size=2, # 张量并行
pipeline_parallel_size = 2, # 流水线并行
data_parallel_size = 2
)
TP 和 PP 很好理解,而DP 的意思应该是,例如你有4张卡,设置 TP = 2 , PP = 1 ,此时 vLLM 内部会启动“两份模型”, 进行并行的数据处理
MoE
部署 DeepSeek-R1 这类超大 Mixture-of-Experts(MoE)模型时,问题不只是“有多少块 GPU”,而是这些 GPU 怎么配合工作。
- 选错并行策略→ KV cache 被复制 8 倍、显存直接爆掉,或者通信开销占了一半时间、吞吐被腰斩。
- 选对并行策略→ 同样硬件上,针对业务场景,性能明显提升。
Expert Parallelism(EP,专家并行)是专为 MoE 模型设计的“修饰开关“,需要和 TP 或 DP 组合使用
概念:Sharded Experts vs Split Experts
| 维度 | Sharded Experts | Split Experts |
|---|---|---|
| 定义 | 每块GPU持有全部专家,单个专家的权重张量在多GPU间分片存储 | 专家整体分发至不同GPU,每块GPU仅持有部分完整专家 |
| 使用 | 不开 –enable-expert-parallel | 开启 –enable-expert-parallel |
| 示例 (256个专家,TP=8) |
每块GPU均有256个专家,单个专家权重仅存1/8 | TP=8+EP, 每块GPU仅存32个完整专家(GPU0:0-31、GPU1:32-63…) |
| 并行组合 | 仅搭配张量并行(TP) | 可搭配张量并行(TP)+专家并行(EP),还可结合数据并行(DP) |
| 通信方式 | 通过AllReduce聚合分片计算结果 | 1. 与DP结合:用AllToAll完成token与专家路由 2. 仅与TP结合:用AllReduce |
| 存储特点 | 单专家权重分片,无完整专家独占GPU | 单GPU存储完整专家,专家整体分布式部署 |
EP 开关控制什么?
- 不开 EP:每块 GPU 上都有全部专家,权重张量被切片(shard),使用AllReduce 聚合;
- 开EP:专家在 GPU 之间做分布(split),当 DP > 1 时:使用 AllToAll(DP Attention);当DP = 1、只有 TP 时:仍然是 AllReduce。
MoE 并行常见误区
- 误区1:“Expert Parallelism 是一种单独的并行方式” ———— 不是,而是开关
--enable-expert-parallel,改写 MoE 层通信与映射方式,只能和 TP 或 DP 搭配使用- 注意:只有当 TP_SIZE × DP_SIZE > 1 时,EP 才会真正生效,否则会被直接忽略
- 误区2:“DP Attention 就是普通的数据并行” ———— MoE 模型上,vLLM 用特殊的 “DP Attention”,和 Data Parallelism 完全不同。
- 误区3:“所有 experts 在 MoE 中都是一样的”———— 不对,MoE 模型中两类 expert行为截然不同。
- 误区4:“TP+EP 通信和 DP+EP 一样都是 AllToAll” ———— TP+EP 只用 AllReduce,完全不会走 AllToAll。vLLM 源码中,AllToAll kernel 的启用条件是:dp_size > 1
DP vs DP Attention
名词区分
传统 DP(Data Parallelism)
- 每块 GPU(或一个 TP 组)上都有完整一份模型副本
- 各副本处理不同请求,互不通信(推理阶段)
DP Attention
- 仍用
--data-parallel-size N配置,但语义:在一个逻辑「大模型副本」内部做请求级并行 - Attention 层是复制的,而 MoE 层的行为取决于是否开 EP
- 推理过程中需要 AllGather / AllToAll / slice 等操作,在 GPU 间反复重排 batch
- 只能在:
- ■ 搭配 EP:形成「DP + EP」
- ■ 不搭 EP:退化为传统 DP,不再具备 KV cache 分区收益
TP 对 MLA/MQA 的问题
Multi-Latent Attention(MLA)与 Multi-Query Attention(MQA)只有一个 KV 头:
- TP 可以按 head 维把 Q/K/V 的线性层切片
- 但KV cache 只有一个 head,没法再按head 维度切
结果:
- KV cache 在所有 TP rank 上完整复制
例子:TP=32 时:
- 线性层计算:每块 GPU 只算 1/32 的 head ✅
- KV cache:每块 GPU 都有 完整副本❌
- 显存浪费极其严重
DP Attention 不再是「多个独立模型副本」,而是一个逻辑模型内部的分工:
- 每块 GPU 上都有完整的非 MoE 层(attention、dense)
- 但 KV cache 按请求 / token 维度切分:
- 每块 GPU 只存自己负责那一部分请求的 KV cache
- 推理时通过 AllToAll 在 GPU 之间互相转发 token
对比传统 DP:
- 传统 DP:每块 GPU 处理自己的 batch,KV cache 完整复制在每个副本中
- DP Attention:一个「逻辑 batch」被拆散,KV cache 被分布到多个 GPU
示例:TP=4,DP=8(共 32 块 GPU)
- 32 块 GPU = 8 个 DP 组 × 每组 4 块 GPU 做 TP
- 非 MoE 计算:每块 GPU 算 1/4 的 head(组内 TP)
- KV cache:每个 DP 组只持有自己请求的 KV,组内 4 块再细分
- AllReduce:只在每个 4-GPU TP 组内做,不跨 32 块全局
- 不同 DP 组之间处理的是完全不同的一批请求
可用性
- MoE + DP Attention 在 vLLM v0.9.0+ 的 V1 engine 中可用,
- 是为 DeepSeek-V2/V3/R1 这类 MLA/MQA 架构专门设计的。
MoE Expert 种类
MoE 模型中通常有两类 expert,行为截然不同。
Routed Experts
- 通过路由机制按需激活
- 每个token 只会激活一小部分 expert(例如 256 中激活 8 个)
- EP 开启时:通过 determine_expert_map 把 routed expert 分布到不同 GPU
- EP 关闭时:所有 routed expert 在每块 GPU 上都存在,但权重会按 flatten_tp_across_dp做切片
- DeepSeek-R1:有 256 个 routed experts
Shared Experts
- 每个 token 都会激活(没有路由)
- 更像一层普通的 dense MLP
- 默认情况权重也是切片存储,只有在以下条件同时满足时才会复制
vLLM 源码解析
【2024-4-12】图解大模型计算加速系列:vLLM源码解析2,调度器策略(Scheduler)
- 一、入口函数
- 二、SequenceGroup
- 2.1 原生请求输入
- 2.2 SequenceGroup的作用
- 2.3 SequenceGroup的结构
- 三、add_request: 预处理请求
- 四、step:调度器策略
- 4.1 调度器结构
- 4.2 整体调度流程
- 4.3 _passed_delay:waiting队列调度时间阈值判断
- 4.4 can_allocate:能否为seq_group分配物理块(prefill)
- 4.5 can_append_slot: 能否为seq_group分配物理块(decode)
- 4.6 allocate与append_slot:为seq_group实际分配物理块
- 4.7 preempt:抢占策略
- 4.8 调度器整体代码解读
案例
‘qwen-vllm - 通义千问VLLM推理部署DEMO’
- GitHub: qwen-vllm
支付宝打赏
微信打赏