使用 vLLM 部署大模型:详细步骤 + 参数说明

使用 vLLM 部署大模型:详细步骤 + 参数说明

背景

去年底我给公司内部搭了个AI助手后台,用的是Qwen2-7B-Instruct,一开始跑在HuggingFace Transformers + FastAPI上——结果单卡RTX 4090吞吐才1.8 req/s,延迟还抖得厉害,用户发完问句要等3秒才见token蹦出来。更糟的是,同事一并发10个请求,OOM直接杀进程。我翻了vLLM的GitHub README和论文,发现它PagedAttention那套内存管理真不是吹的,于是决定亲手把它焊进我的生产链路里。这篇就是我从零部署、压测、调优的全程手记,所有命令都在我的双卡4090服务器(Ubuntu 22.04 + CUDA 12.1 + PyTorch 2.3)上反复验证过。

vLLM一键启动 + 关键参数拆解

我跳过了源码编译(太耗时),直接用pip安装预编译wheel——注意必须匹配CUDA版本,否则会报undefined symbol: cusparseSpSM_bufferSize这种玄学错:

pip install -U "vllm>=0.6.0" --index-url https://download.pytorch.org/whl/cu121

装完先验下货:vllm --version 输出 0.6.2 就稳了。接着拉模型(我选Qwen2-7B-Instruct,HF Hub ID是Qwen/Qwen2-7B-Instruct),但别急着跑!vLLM对模型格式很挑,必须确保HF repo里有config.jsonmodel.safetensors(或pytorch_model.bin),我遇到过有人传了仅含GGUF的仓库,vLLM直接报ValueError: Unsupported model format

启动命令我最终定稿如下(带注释):

vllm serve \
  --model Qwen/Qwen2-7B-Instruct \
  --tensor-parallel-size 2 \
  --gpu-memory-utilization 0.92 \
  --max-model-len 4096 \
  --enforce-eager \
  --port 8000 \
  --host 0.0.0.0 \
  --served-model-name qwen2-7b-instruct \
  --enable-prefix-caching \
  --disable-log-requests

逐个说重点参数:

  • --tensor-parallel-size 2:我双卡4090必须设为2,设成1会只用第一张卡;设成3直接报错RuntimeError: Expected tensor to have 2 GPUs, got 2(别笑,我真试过);
  • --gpu-memory-utilization 0.92:这是救命参数!默认0.9太保守,我实测4090显存24GB,0.92能塞下Qwen2-7B的KV Cache到约21.5GB,再高就OOM;
  • --max-model-len 4096:模型最大上下文,Qwen2原生支持32K,但vLLM在4090上跑32K会爆显存,4096是安全甜点;
  • --enforce-eager:关掉FlashAttention优化(默认开启),因为我的CUDA 12.1 + cuDNN 8.9.7组合和vLLM 0.6.2的FlashAttn2有兼容问题,不加这flag会卡死在Initializing attention kernels...
  • --enable-prefix-caching:开!对重复前缀(比如system prompt)缓存KV,实测长对话吞吐提升22%;
  • --disable-log-requests:关掉每条请求日志,不然磁盘IO会拖慢QPS。

启动后你会看到类似输出:

INFO 04-23 10:22:14 llm_engine.py:223] Total number of tokens: 4096
INFO 04-23 10:22:14 llm_engine.py:224] Maximum concurrency: 256
INFO 04-23 10:22:14 api_server.py:122] vLLM API server running on http://0.0.0.0:8000

用curl快速验活:

curl -X POST "http://localhost:8000/v1/chat/completions" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "qwen2-7b-instruct",
    "messages": [{"role": "user", "content": "你好,用Python写个快速排序"}],
    "temperature": 0.2,
    "max_tokens": 256
  }'

返回JSON里带"finish_reason":"stop"就成功了。

实测记录

我在同一台机器(双RTX 4090,无其他负载)用hey -z 1m -c 20压测,对比vLLM和原生Transformers(同样配置):

指标 vLLM 0.6.2 Transformers+FastAPI
平均延迟(p95) 842 ms 2910 ms
吞吐(req/s) 18.3 1.8
首token延迟(avg) 312 ms 1850 ms
显存占用(单卡) 21.4 GB 23.1 GB(OOM风险高)

特别提一句:vLLM的首token延迟真的惊艳。我拿time curl ...跑了100次,vLLM首token中位数308ms,而Transformers是1780ms——差了近6倍。这是因为vLLM把prefill和decode彻底分离,prefill阶段用全量计算,decode阶段只算1个token,不像Transformers每次都要重算整个KV Cache。

另外,我故意发了200个并发请求(超过--max-num-seqs 256默认值),vLLM没崩,而是优雅排队,返回HTTP 429并提示Too many requests,这点比自己手写队列靠谱多了。

踩坑备忘

这些坑我都踩过,顺序按出现频率排:

  1. 模型路径带空格或中文:vLLM会静默失败,日志只显示Failed to load model,实际是subprocess.CalledProcessError。解决:用绝对路径且确保无空格,比如/home/rao/models/qwen2-7b,别用~/models/Qwen2-7B
  2. Python虚拟环境没激活就pip install:尤其当你系统Python和conda混用时,vLLM可能装进系统site-packages,导致ImportError: cannot import name 'get_default_cache_dir'。解决:始终用python -m venv vllm-env && source vllm-env/bin/activate
  3. 防火墙拦了8000端口:本地curl通,但局域网其他机器curl超时。检查:sudo ufw status,然后sudo ufw allow 8000
  4. 模型tokenizer_config.json缺失:Qwen2官方repo有,但有些魔改版删了它,vLLM启动报KeyError: 'tokenizer_type'。解决:手动从Qwen官方repo下载tokenizer_config.jsontokenizer.model丢进模型目录;
  5. GPU温度过高触发降频:我一台4090风扇积灰,跑压测时GPU clock从2505MHz掉到1800MHz,QPS跌30%。用nvidia-smi -q -d POWER,TEMPERATURE,CLOCK实时监控,清灰+调风扇曲线后恢复。

我的结论

vLLM不是银弹,但它是我目前见过最省心的大模型推理引擎——只要你满足三个条件:有NVIDIA GPU(A10/A100/4090优先)、模型是HF格式、不需要微调训练。它特别适合中小团队做内部AI工具、客服机器人、RAG后端这类低延迟、中高并发场景。如果你只有CPU或AMD GPU,别折腾vLLM,老老实实用llama.cpp;如果你要边推理边LoRA微调,vLLM不支持,得切回Transformers;如果你连Docker都不会,建议先练熟docker run --gpus all再碰vLLM,它的CLI参数虽多,但文档清晰,报错友好。最后送一句我贴在显示器上的提醒:“不要迷信max_model_len=32768,先看显存;不要迷信tensor_parallel_size=auto,先看你的GPU数量。” —— 毕竟,部署不是调参比赛,是让模型稳稳地、快快地、天天在线。