性能优化
本章介绍如何通过量化、并行和配置调优来提升 vLLM 的推理性能。
量化技术
量化通过降低模型权重和计算的精度来减少显存占用和加速推理。vLLM 支持多种量化方法,包括 AWQ、GPTQ、FP8、INT8 等。
快速选择指南
| 场景 | 推荐量化 | 理由 |
|---|---|---|
| 消费级 GPU(24GB 以下) | AWQ/GPTQ 4-bit | 最大化显存节省 |
| 专业 GPU(A100/H100) | FP8 或 INT8 | 平衡精度和速度 |
| Hopper GPU(H100/H200) | FP8 | 原生硬件支持 |
| 精度敏感应用 | INT8 | 精度损失最小 |
使用示例
from vllm import LLM
# AWQ 量化(4-bit,显存节省约 65%)
llm = LLM(
model="TheBloke/Llama-2-7B-AWQ",
quantization="awq"
)
# FP8 量化(Hopper GPU)
llm = LLM(
model="meta-llama/Llama-2-7b-chat-hf",
quantization="fp8"
)
量化技术的详细原理、配置方法和最佳实践请参考 量化详解 章节。
并行策略
张量并行(Tensor Parallelism)
张量并行将模型权重沿维度分割到多个 GPU:
vllm serve meta-llama/Llama-2-70b-chat-hf \
--tensor-parallel-size 4
from vllm import LLM
llm = LLM(
model="meta-llama/Llama-2-70b-chat-hf",
tensor_parallel_size=4
)
适用场景:
- 单个 GPU 无法容纳模型
- 需要最大化吞吐量
流水线并行(Pipeline Parallelism)
流水线并行将模型层分割到不同 GPU:
from vllm import LLM
llm = LLM(
model="meta-llama/Llama-2-70b-chat-hf",
pipeline_parallel_size=4, # 4 个 GPU 流水并行
tensor_parallel_size=2 # 每个流水线阶段内部 2 卡张量并行
)
数据并行(Data Parallelism)
数据并行用于扩展服务能力:
# 启动多个实例
vllm serve meta-llama/Llama-2-7b-chat-hf --port 8000 &
vllm serve meta-llama/Llama-2-7b-chat-hf --port 8001 &
# 使用负载均衡器分发请求
LoRA 适配器支持
LoRA(Low-Rank Adaptation)是一种轻量级的模型微调方法,通过在原模型旁边添加少量可训练参数来实现定制化。vLLM 支持在推理时动态加载和切换多个 LoRA 适配器,极大降低了部署多个定制模型的成本。
为什么使用 LoRA
传统方式部署多个定制模型需要为每个模型加载完整的权重,显存开销巨大。例如,部署 10 个微调版本的 Llama-2-7B,需要约 140GB 显存(每个模型约 14GB)。
使用 LoRA 后,只需加载一个基础模型(14GB)和 10 个小型 LoRA 适配器(每个约 100MB),总显存仅需约 15GB。
离线推理中使用 LoRA
from vllm import LLM, SamplingParams
from vllm.lora.request import LoRARequest
from huggingface_hub import snapshot_download
# 下载 LoRA 适配器
sql_lora_path = snapshot_download(repo_id="yard1/llama-2-7b-sql-lora-test")
# 创建基础模型并启用 LoRA
llm = LLM(
model="meta-llama/Llama-2-7b-hf",
enable_lora=True,
max_lora_rank=64 # 设置 LoRA 的最大秩
)
# 定义采样参数
sampling_params = SamplingParams(
temperature=0,
max_tokens=256
)
# 定义提示词
prompts = [
"Write a SQL query to find all users over 25 years old.",
"Write a SQL query to count orders by status."
]
# 使用 LoRA 适配器生成
outputs = llm.generate(
prompts,
sampling_params,
lora_request=LoRARequest(
"sql_adapter", # 适配器名称
1, # 全局唯一 ID
sql_lora_path # LoRA 适配器路径
)
)
for output in outputs:
print(output.outputs[0].text)
服务端部署 LoRA
启动服务时指定 LoRA 模块:
vllm serve meta-llama/Llama-2-7b-hf \
--enable-lora \
--lora-modules sql-lora=/path/to/sql-lora-adapter \
--max-lora-rank 64
同时加载多个 LoRA 适配器:
vllm serve meta-llama/Llama-2-7b-hf \
--enable-lora \
--lora-modules \
sql-lora=/path/to/sql-lora \
chat-lora=/path/to/chat-lora \
code-lora=/path/to/code-lora \
--max-lora-rank 64
使用 JSON 格式指定基础模型信息:
vllm serve meta-llama/Llama-2-7b-hf \
--enable-lora \
--lora-modules '{"name": "sql-lora", "path": "/path/to/sql-lora", "base_model_name": "meta-llama/Llama-2-7b-hf"}'
客户端调用 LoRA 模型
使用 OpenAI 客户端调用 LoRA 适配器:
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8000/v1",
api_key="not-needed"
)
# 指定 LoRA 模型名称
response = client.chat.completions.create(
model="sql-lora", # 使用 sql-lora 适配器
messages=[
{"role": "user", "content": "Write a SQL query to find active users."}
]
)
print(response.choices[0].message.content)
使用 curl 调用:
curl http://localhost:8000/v1/completions \
-H "Content-Type: application/json" \
-d '{
"model": "sql-lora",
"prompt": "Write a SQL query to select all products.",
"max_tokens": 100
}'
动态加载 LoRA 适配器
vLLM 支持在运行时动态加载和卸载 LoRA 适配器:
# 启用动态 LoRA 更新
export VLLM_ALLOW_RUNTIME_LORA_UPDATING=True
vllm serve meta-llama/Llama-2-7b-hf --enable-lora
动态加载适配器:
curl -X POST http://localhost:8000/v1/load_lora_adapter \
-H "Content-Type: application/json" \
-d '{
"lora_name": "new-adapter",
"lora_path": "/path/to/new-lora-adapter"
}'
动态卸载适配器:
curl -X POST http://localhost:8000/v1/unload_lora_adapter \
-H "Content-Type: application/json" \
-d '{
"lora_name": "new-adapter"
}'
LoRA 配置参数
| 参数 | 说明 | 默认值 |
|---|---|---|
max_lora_rank | LoRA 的最大秩 | 16 |
max_loras | 同时加载的最大 LoRA 数量 | 1 |
max_cpu_loras | CPU 上缓存的 LoRA 数量 | 与 max_loras 相同 |
lora_extra_vocab_size | LoRA 额外词汇表大小 | 256 |
llm = LLM(
model="meta-llama/Llama-2-7b-hf",
enable_lora=True,
max_lora_rank=64, # 设置最大秩
max_loras=4, # 同时加载 4 个 LoRA
max_cpu_loras=8 # CPU 缓存 8 个 LoRA
)
配置 max_lora_rank 的建议
max_lora_rank 参数影响内存分配和性能:
- 设置为所有 LoRA 适配器中的最大秩值
- 不要设置过高,会浪费内存并影响性能
- 如果 LoRA 适配器的秩分别为 [16, 32, 64],应使用
--max-lora-rank 64
关键参数调优
显存利用率
from vllm import LLM
# 默认 0.9,保守值 0.8
llm = LLM(
model="meta-llama/Llama-2-7b-chat-hf",
gpu_memory_utilization=0.85, # 留出更多显存给其他任务
max_model_len=4096
)
最大序列长度
llm = LLM(
model="meta-llama/Llama-2-7b-chat-hf",
max_model_len=8192, # 根据实际需求设置
max_num_seqs=256 # 最大并发数
)
批处理参数
llm = LLM(
model="meta-llama/Llama-2-7b-chat-hf",
max_num_seqs=256, # 最大并发序列数
max_num_batched_tokens=8192, # 单批次最大 token 数
max_model_len=4096
)
性能基准测试
使用 benchmark 脚本
# 安装 benchmark 工具
pip install vllm[benchmark]
# 运行吞吐量测试
python -m vllm benchmark throughput \
--model meta-llama/Llama-2-7b-chat-hf \
--num-prompts 1000 \
--input-len 512 \
--output-len 128
自定义性能测试
import time
from vllm import LLM, SamplingParams
llm = LLM(model="meta-llama/Llama-2-7b-chat-hf")
sampling_params = SamplingParams(temperature=0.7, max_tokens=100)
prompts = ["测试提示词"] * 100
# 预热
llm.generate(prompts[:10], sampling_params)
# 正式测试
start = time.time()
outputs = llm.generate(prompts, sampling_params)
end = time.time()
total_tokens = sum(len(o.outputs[0].token_ids) for o in outputs)
throughput = total_tokens / (end - start)
print(f"总耗时: {end - start:.2f}s")
print(f"总 token 数: {total_tokens}")
print(f"吞吐量: {throughput:.2f} tokens/s")
常见性能问题
延迟过高
检查项:
- 确认 GPU 利用率
- 检查 batch size 是否合适
- 启用 Chunked Prefill
llm = LLM(
model="meta-llama/Llama-2-7b-chat-hf",
enable_chunked_prefill=True,
max_num_batched_tokens=2048
)
显存不足(OOM)
解决方案:
llm = LLM(
model="meta-llama/Llama-2-7b-chat-hf",
gpu_memory_utilization=0.7, # 降低显存使用
max_model_len=2048, # 限制最大序列长度
quantization="fp8" # 启用量化
)
吞吐量低
优化方向:
llm = LLM(
model="meta-llama/Llama-2-7b-chat-hf",
max_num_seqs=512, # 提高并发数
max_num_batched_tokens=16384, # 增加批次大小
enable_chunked_prefill=True
)
小结
性能优化需要根据实际场景选择合适的策略:
- 量化:首选 FP8(Hopper)或 AWQ,减少显存占用
- 并行:根据模型大小和 GPU 数量选择合适的并行策略
- 参数调优:调整 max_model_len 和批处理参数找到最优配置
- 测试验证:使用 benchmark 工具验证优化效果