4、单GPU部署入门:使用vLLM在单卡上启动LLM服务,验证推理正确性

在完成多GPU分布式部署之前,必须先扎实掌握单GPU上的vLLM部署。单卡环境是分布式系统的“最小单元”,所有分布式推理中的核心机制——PagedAttention显存管理、Continuous Batching连续批处理、KV Cache复用——在单卡上同样生效。只有先在单卡上验证模型加载、推理输出、性能指标的正确性,后续扩展到多卡时才能准确区分“模型问题”与“并行策略问题”。本章将带领你从环境准备开始,完成一次完整的单卡部署,并通过结构化方法验证推理正确性。

单GPU vLLM部署验证链路 环境准备 CUDA 12.x / PyTorch 2.x vLLM 0.6+ / GPU驱动 模型加载 LLM(model_path, tensor_parallel_size=1) 推理请求 llm.generate(prompts, sampling_params) 输出验证 文本/性能/ 显存指标 核心机制:PagedAttention + Continuous Batching + KV Cache 验证维度 ① 文本正确性(语义/格式) ② 性能指标(TTFT/TPOT) ③ 显存占用(KV Cache) ④ 并发一致性(多请求) 常见误区 ✗ 忽略采样参数影响 ✗ 仅看输出长度 ✗ 未检查GPU显存碎片 ✗ 混淆tensor并行与batch 输出示例 Prompt: "什么是注意力机制?" Output: "注意力机制是一种..." TTFT: 0.32s | TPOT: 45ms GPU Mem: 12.4GB / 24GB

4.1 核心原理:单卡部署中的关键机制

vLLM在单GPU上的部署并非简单的“加载模型+推理”,其核心优势在于三个关键机制:PagedAttention、Continuous Batching和KV Cache管理。PagedAttention将KV Cache划分为固定大小的块(默认16个token),按需分配,避免了传统推理中预分配最大长度导致的显存浪费。Continuous Batching允许vLLM在迭代级别动态调度请求,当一个请求完成生成时,新请求可以立即插入当前批次,而不是等待整个批次结束。KV Cache则缓存了注意力机制中的Key和Value矩阵,避免重复计算。

在单卡场景下,这些机制的效果最为直观:显存利用率通常比HuggingFace Transformers原生推理提升2-4倍,吞吐量提升10-20倍。理解这些机制有助于后续诊断多GPU环境下的性能瓶颈——例如,当tensor parallel size增大时,KV Cache的通信开销会成为新的瓶颈。

关键参数说明:在单卡部署时,tensor_parallel_size=1是默认值,表示不进行张量并行。此时模型的所有层都驻留在单张GPU上。若显存不足,可考虑max_model_len(最大序列长度)和gpu_memory_utilization(GPU显存利用率上限,默认0.9)两个参数进行调节。

4.2 操作流程:从环境准备到服务启动

单卡部署的标准流程分为四个阶段:环境准备、模型加载、推理执行、结果验证。以下以Qwen2.5-7B-Instruct模型为例,展示完整操作步骤。

4.2.1 环境准备

# 创建虚拟环境(Python 3.10+)
python -m venv vllm_env
source vllm_env/bin/activate

# 安装PyTorch(以CUDA 12.1为例)
pip install torch==2.3.0 torchvision==0.18.0 --index-url https://download.pytorch.org/whl/cu121

# 安装vLLM
pip install vllm==0.6.3

# 验证安装
python -c "import vllm; print(vllm.__version__)"

安装完成后,使用nvidia-smi确认GPU驱动正常,并记录GPU型号与显存大小。对于7B模型,建议至少16GB显存;若使用13B模型,则需要24GB以上。

4.2.2 模型加载与推理脚本

from vllm import LLM, SamplingParams
import time

# 初始化模型(单卡)
llm = LLM(
    model="Qwen/Qwen2.5-7B-Instruct",
    tensor_parallel_size=1,          # 单卡关键参数
    gpu_memory_utilization=0.85,     # 预留15%显存给CUDA context
    max_model_len=4096,              # 最大序列长度
    trust_remote_code=True
)

# 构造测试prompt
prompts = [
    "请简要解释什么是Transformer架构?",
    "写一首关于秋天的五言绝句。",
    "1+1等于几?请直接回答数字。"
]

# 设置采样参数
sampling_params = SamplingParams(
    temperature=0.7,
    top_p=0.9,
    max_tokens=256,
    stop=["\n\n"]  # 可选停止符
)

# 执行推理
start_time = time.time()
outputs = llm.generate(prompts, sampling_params)
elapsed = time.time() - start_time

# 打印结果
for i, output in enumerate(outputs):
    prompt_text = output.prompt
    generated_text = output.outputs[0].text
    print(f"Prompt {i+1}: {prompt_text}")
    print(f"Generated: {generated_text}")
    print(f"Tokens: {len(output.outputs[0].token_ids)}")
    print("-" * 50)

print(f"总耗时: {elapsed:.2f}s")

4.2.3 启动OpenAI兼容服务

除了直接调用Python API,vLLM还提供了OpenAI兼容的HTTP服务,便于集成到现有应用中:

# 命令行启动服务
python -m vllm.entrypoints.openai.api_server \
    --model Qwen/Qwen2.5-7B-Instruct \
    --tensor-parallel-size 1 \
    --host 0.0.0.0 \
    --port 8000 \
    --gpu-memory-utilization 0.85

# 使用curl测试
curl http://localhost:8000/v1/completions \
    -H "Content-Type: application/json" \
    -d '{"model": "Qwen/Qwen2.5-7B-Instruct", "prompt": "什么是深度学习?", "max_tokens": 128}'

4.3 案例拆解:验证推理正确性的完整闭环

以下通过一个实际案例,展示如何系统性地验证推理正确性。假设我们部署了Meta-Llama-3-8B-Instruct模型,目标是确认其在单卡上的输出质量与HuggingFace基线一致。

验证维度测试方法预期结果实际结果结论
文本语义同一prompt对比HF输出核心语义一致语义一致,措辞略有差异✅ 通过
数学推理"17*23=?"输出391输出391✅ 通过
代码生成"写Python快排"可运行代码代码正确,缩进规范✅ 通过
长文本输入2000字文章不崩溃,输出连贯正常生成,无截断✅ 通过
并发请求同时发送10个请求全部成功9成功,1超时⚠️ 需调参

在并发测试中,发现1个请求超时。分析vllm.log发现超时请求的输入长度为1800 tokens,而其他请求平均为200 tokens。这是因为max_num_seqs(默认256)和max_model_len共同限制了批处理能力。解决方案是将max_num_seqs调整为64,并设置max_paddings=128,以平衡吞吐与延迟。

经验提醒:验证推理正确性时,不要只依赖单一指标。建议使用困惑度(Perplexity)作为客观指标,同时结合人工评估。对于生成类任务,可以计算输出文本的BLEU或ROUGE分数与参考文本对比。

4.4 常见误区与总结复盘

在单卡部署过程中,初学者常犯以下错误,这些错误在多GPU环境下会被放大:

  • 误区一:忽略采样参数的影响。使用默认的temperature=1.0可能导致输出随机性过大,难以复现。建议在验证阶段使用temperature=0(贪心解码)确保确定性。
  • 误区二:仅检查输出长度。模型可能生成重复文本或陷入死循环。应检查输出文本的多样性指标(如distinct-n)和终止原因(finish_reason)。
  • 误区三:未监控显存碎片。vLLM的PagedAttention虽然高效,但长时间运行后仍可能产生碎片。使用nvidia-smi观察显存使用率,若持续增长但吞吐下降,需重启服务。
  • 误区四:混淆tensor并行与数据并行。单卡部署时tensor_parallel_size=1,但有些用户误以为设置--tensor-parallel-size 2可以加速单卡推理,这反而会导致显存翻倍并报错。
风险提示:当gpu_memory_utilization设置过高(>0.95)时,可能触发CUDA Out of Memory。建议保留至少5%显存给CUDA context和PyTorch运行时。若遇到OOM,优先降低max_model_len或max_num_seqs,而不是盲目降低gpu_memory_utilization。

总结复盘:单GPU部署是vLLM的“最小可行验证”环境。通过本章学习,你应掌握:① 环境搭建与参数配置;② 使用Python API和HTTP服务两种方式启动推理;③ 从文本、性能、显存、并发四个维度验证正确性;④ 识别并规避常见配置陷阱。这些能力将直接迁移到多GPU场景——例如,在设置tensor_parallel_size=2之前,先确保单卡推理输出与基线一致,否则无法判断多卡结果偏差是模型问题还是并行策略问题。

在下一阶段,当你准备扩展到多GPU时,请记住:单卡验证是分布式部署的“回归测试基线”。任何多卡配置的改动,都应回到单卡结果进行对比,确保分布式引入的通信开销没有破坏模型原有的推理质量。