vLLM常用启动参数的调整思路与实战步骤

描述

 

问题背景

vLLM 是当前最流行的大模型推理加速框架之一,通过 PagedAttention、连续批处理等技术显著提升推理吞吐量。但默认启动参数并不适配所有业务场景,盲目使用可能导致 GPU 显存浪费、队列积压、OOM 崩溃或性能不达预期。

运维人员在部署 vLLM 时经常遇到这些问题:启动后显存占用过高导致无法部署多个服务、并发处理能力不符合预期、队列堆积严重、某些请求被拒绝、GPU 利用率低但吞吐量仍不足。这些问题往往源于启动参数配置不当。

本文面向已部署或即将部署 vLLM 推理服务的运维工程师和 SRE,梳理 vLLM 常用启动参数的含义、默认值、适用场景、调整依据和风险点,帮助根据实际业务特点调优配置。

适用场景

  • 首次部署 vLLM 推理服务,需要确定合理的启动参数
  • vLLM 服务已部署,但性能不达预期,需要调优
  • 需要在有限 GPU 资源上部署多个模型或多个副本
  • 需要根据业务特点(输入输出长度、并发模式、延迟要求)定制配置
  • 需要在成本、延迟、吞吐量之间做权衡

核心知识点

vLLM 的核心机制

  1. PagedAttention:将 KV Cache 分块管理,类似操作系统的虚拟内存分页,大幅降低显存碎片
  2. Continuous Batching:持续批处理,新请求可以动态加入正在推理的批次,避免空转等待
  3. KV Cache 预分配:启动时预分配显存块,避免推理时频繁分配释放

关键参数分类

  1. 模型相关:模型路径、数据类型、张量并行度、流水线并行度
  2. 显存相关:GPU 显存使用比例、KV Cache 块大小、换入换出策略
  3. 并发相关:最大并发序列数、批处理大小、调度策略
  4. 性能相关:预填充分块、推测解码、量化方法
  5. 服务相关:监听地址、端口、API 模式、日志级别

参数调整的权衡

  • 显存使用率 vs 并发能力:预留更多显存给 KV Cache 可以提升并发,但会限制其他服务或模型部署
  • 批处理大小 vs 延迟:更大的批处理提升吞吐量,但可能增加排队延迟
  • 数据精度 vs 准确性:低精度(FP8、INT8)节省显存和计算,但可能影响模型输出质量
  • 预填充分块 vs TTFT:分块预填充降低首字延迟,但可能略微降低总吞吐量

整体调整思路

调整前的准备工作

  1. 明确业务特点:

  • 平均输入长度、输出长度
  • 并发请求数的峰值和平均值
  • 对延迟的容忍度(实时对话 vs 批量生成)
  • 是否需要流式输出
  • 了解硬件环境:

  • GPU 型号和显存大小
  • 单卡还是多卡
  • 是否需要在同一 GPU 上部署多个模型
  • 确定性能目标:

  • TTFT 目标值(如 P99 < 500ms)
  • TPS 目标值(如 > 50 tokens/s)
  • 最大并发数要求

调整策略

  1. 从默认值开始:先使用默认参数启动,观察显存占用、并发能力和性能指标
  2. 识别瓶颈:通过监控判断瓶颈在显存、并发数、队列还是计算
  3. 逐个调整:每次只调整一个参数,观察效果,避免多参数叠加难以定位问题
  4. 压测验证:调整后进行压力测试,确认是否达到预期

实战步骤

第一步:查看 vLLM 支持的启动参数


			   bashpython -m vllm.entrypoints.openai.api_server --help 

预期输出(部分):


			   usage: api_server.py [-h] --model MODEL [--tokenizer TOKENIZER]                      [--revision REVISION] [--tokenizer-revision TOKENIZER_REVISION]                      [--tokenizer-mode {auto,slow}]                      [--trust-remote-code]                      [--download-dir DOWNLOAD_DIR]                      [--load-format {auto,pt,safetensors,npcache,dummy}]                      [--dtype {auto,half,float16,bfloat16,float,float32}]                      [--kv-cache-dtype {auto,fp8}]                      [--max-model-len MAX_MODEL_LEN]                      [--guided-decoding-backend {outlines,lm-format-enforcer}]                      [--worker-use-ray]                      [--pipeline-parallel-size PIPELINE_PARALLEL_SIZE]                      [--tensor-parallel-size TENSOR_PARALLEL_SIZE]                      [--max-parallel-loading-workers MAX_PARALLEL_LOADING_WORKERS]                      [--block-size BLOCK_SIZE]                      [--seed SEED]                      [--swap-space SWAP_SPACE]                      [--gpu-memory-utilization GPU_MEMORY_UTILIZATION]                      [--max-num-batched-tokens MAX_NUM_BATCHED_TOKENS]                      [--max-num-seqs MAX_NUM_SEQS]                      ... 

第二步:理解核心启动参数

1. --model

含义:模型路径或 HuggingFace 模型标识。

默认值:无,必填参数。

示例:


			   bash--model /models/llama-2-7b-chat --model meta-llama/Llama-2-7b-chat-hf 

调整建议:

  • 本地路径:模型文件已下载到本地,避免启动时联网下载
  • HuggingFace 标识:首次启动会自动下载,需要网络访问和足够的磁盘空间
  • 生产环境建议使用本地路径,避免依赖外部网络

2. --dtype

含义:模型推理时使用的数据类型。

默认值:auto(自动检测模型配置中的 dtype)。

可选值:autohalffloat16bfloat16floatfloat32

示例:


			   bash--dtype bfloat16 --dtype float16 

调整建议:

  • float16:适合大多数 GPU,显存占用是 float32 的一半
  • bfloat16:适合 A100、H100 等支持 BF16 的 GPU,数值稳定性优于 float16
  • float32:精度最高但显存占用大,一般不推荐
  • auto:让 vLLM 根据模型配置自动选择,通常是合理的默认值

判断逻辑:

  • 如果 GPU 支持 BF16(A100、H100),优先使用 bfloat16
  • 如果 GPU 不支持 BF16,使用 float16
  • 如果模型输出质量不符合预期,可以尝试提升精度

3. --tensor-parallel-size

含义:张量并行度,将模型参数分布到多个 GPU 上。

默认值:1(不使用张量并行)。

示例:


			   bash--tensor-parallel-size 2 --tensor-parallel-size 4 

调整建议:

  • 当单个 GPU 显存无法容纳模型时,使用张量并行
  • 张量并行度应为 GPU 数量的因子(2、4、8)
  • 张量并行会引入 GPU 间通信开销,仅在必要时使用

判断逻辑:

  • 模型参数量 * dtype 字节数 * 1.2(额外开销) > 单卡显存:需要张量并行
  • 例如 Llama-2-70B(70B 参数)+ float16(2 字节):70B * 2 * 1.2 = 168GB,单张 A100 80GB 不够,需要 --tensor-parallel-size 2 或更多

验证方式:


			   bashpython -m vllm.entrypoints.openai.api_server    --model /models/llama-2-70b    --tensor-parallel-size 2 nvidia-smi 

检查每张 GPU 显存占用是否均衡。

4. --gpu-memory-utilization

含义:vLLM 可以使用的 GPU 显存比例。

默认值:0.9(90%)。

取值范围:0.0 - 1.0。

示例:


			   bash--gpu-memory-utilization 0.85 --gpu-memory-utilization 0.95 

调整建议:

  • 调高(0.95 - 0.98):需要最大化并发能力,GPU 上只运行 vLLM 一个服务
  • 调低(0.70 - 0.85):需要在同一 GPU 上部署多个模型或服务,或需要预留显存给其他进程
  • 默认值(0.9):适合大多数场景

判断逻辑:

  • 如果监控显示 KV Cache 使用率长期 > 90%,考虑调高 gpu-memory-utilization
  • 如果 GPU 上需要运行多个服务,根据服务数量等比例分配,例如 2 个服务各 0.45
  • 如果启动时 OOM,考虑调低该值

风险提醒:

  • 设置过高(> 0.98)可能导致 OOM,尤其是模型加载后的初始化阶段
  • 设置过低会浪费显存,降低并发能力

验证方式:


			   bashnvidia-smi --query-gpu=memory.used,memory.total --format=csv,noheader,nounits curl -s http://localhost:8000/metrics | grep gpu_cache_usage_perc 

5. --max-num-seqs

含义:最大并发序列数,即同时处理的请求数上限。

默认值:256

示例:


			   bash--max-num-seqs 128 --max-num-seqs 512 

调整建议:

  • 调高:业务并发高,希望减少排队时间
  • 调低:显存不足,或希望降低单个请求的延迟

判断逻辑:

  • 如果监控显示队列长度长期 > 50,且 GPU 利用率 < 80%,考虑调高
  • 如果启动后 KV Cache 使用率长期 > 95%,考虑调低
  • 该值与 gpu-memory-utilization 和输入输出长度相关,需要综合考虑

典型场景:

场景 推荐值 原因
实时对话(短输入输出) 256 - 512 单个请求显存占用小,可以高并发
长文本生成(长输出) 64 - 128 单个请求显存占用大,降低并发避免 OOM
批量离线处理 128 - 256 平衡吞吐量和资源占用

验证方式:


			   bashcurl -s http://localhost:8000/metrics | grep num_requests_running curl -s http://localhost:8000/metrics | grep num_requests_waiting 

如果 num_requests_running 长期等于 max-num-seqs 且 num_requests_waiting > 0,说明并发能力不足。

6. --max-model-len

含义:模型支持的最大上下文长度(输入 + 输出 tokens 总和)。

默认值:模型配置中的 max_position_embeddings 或 max_sequence_length

示例:


			   bash--max-model-len 4096 --max-model-len 8192 

调整建议:

  • 调低:业务输入输出都不长,降低该值可以节省显存,提升并发
  • 调高:业务需要处理长文本,但需要确认模型本身支持

判断逻辑:

  • 如果业务 95% 的请求输入输出总和 < 2048,而模型支持 8192,可以设置 --max-model-len 2048 节省显存
  • 如果用户请求超过该长度,vLLM 会拒绝请求并返回错误

风险提醒:

  • 设置过低会导致长请求被拒绝
  • 设置过高会浪费显存,降低并发能力
  • 不要超过模型本身的最大支持长度

验证方式:

检查业务日志中是否有请求因长度超限被拒绝:


			   bashdocker logs vllm-container 2>&1 | grep -i "exceed|too long|length" 

7. --block-size

含义:KV Cache 的块大小,单位是 token 数。

默认值:16

可选值:81632

示例:


			   bash--block-size 16 --block-size 32 

调整建议:

  • 调大(32):适合长文本生成场景,降低块管理开销
  • 调小(8):适合短文本场景,降低显存碎片

判断逻辑:

  • 大多数场景使用默认值 16 即可
  • 除非有明确的性能瓶颈,否则不建议修改

风险提醒:

  • 修改该参数会影响 KV Cache 的分配和管理,可能引入未预期的性能变化

8. --swap-space

含义:CPU 内存用于 KV Cache 换出的空间大小,单位 GB。

默认值:4(4GB)。

示例:


			   bash--swap-space 8 --swap-space 0 

调整建议:

  • 调高(8 - 16):业务有长尾请求,希望避免拒绝服务
  • 设为 0:不使用换出,所有请求必须在 GPU 显存内完成,拒绝超出容量的请求

判断逻辑:

  • 如果监控显示 KV Cache 频繁换出(swap),说明显存不足,可以调高 swap-space 或调低 max-num-seqs
  • 如果希望严格控制延迟,避免换出导致的性能抖动,可以设为 0

风险提醒:

  • 换出会引入 CPU-GPU 数据传输,增加延迟
  • 换出功能依赖 CPU 内存,需要确保有足够的可用内存

9. --max-num-batched-tokens

含义:单个批次中最大 token 数量(包括所有请求的输入和已生成的输出)。

默认值:根据 max-model-len 自动计算。

示例:


			   bash--max-num-batched-tokens 8192 --max-num-batched-tokens 16384 

调整建议:

  • 调高:希望提升吞吐量,允许更大的批处理
  • 调低:希望降低首字延迟,减少排队时间

判断逻辑:

  • 如果 TTFT P99 过高,可以适当调低该值
  • 如果 GPU 利用率低但吞吐量不足,可以适当调高该值

风险提醒:

  • 设置过高可能导致 OOM
  • 设置过低会限制批处理能力,降低吞吐量

10. --disable-log-requests

含义:禁用详细的请求日志。

默认值:不禁用(会记录每个请求的详细信息)。

示例:


			   bash--disable-log-requests 

调整建议:

  • 生产环境建议启用:减少 I/O 压力,避免日志文件过大
  • 调试阶段不启用:保留详细日志便于排查问题

判断逻辑:

  • 如果日志文件增长过快(> 10GB/天),影响磁盘 I/O,启用该选项
  • 如果需要排查慢请求或异常请求,暂时关闭该选项

11. --trust-remote-code

含义:是否信任并执行模型仓库中的自定义代码。

默认值:不信任(不执行自定义代码)。

示例:


			   bash--trust-remote-code 

调整建议:

  • 必要时启用:某些模型(如 Qwen、ChatGLM)需要执行自定义代码才能正常加载
  • 安全风险:启用后会执行模型仓库中的 Python 代码,存在安全风险

判断逻辑:

  • 如果启动时报错 ValueError: The model ... requires custom code,需要启用该选项
  • 如果模型来自不可信来源,不要启用

风险提醒:

  • 启用该选项后,模型仓库中的代码可以执行任意操作,包括访问文件系统、网络等
  • 生产环境建议先在隔离环境中测试,确认无风险后再部署

12. --host 和 --port

含义:API 服务监听的地址和端口。

默认值:--host 0.0.0.0 --port 8000

示例:


			   bash--host 127.0.0.1 --port 8001 --host 0.0.0.0 --port 8000 

调整建议:

  • 0.0.0.0:允许外部访问,适合生产环境
  • 127.0.0.1:仅本地访问,适合测试或通过 API Gateway 转发的场景

判断逻辑:

  • 如果需要从其他机器访问,使用 0.0.0.0
  • 如果有多个 vLLM 实例,需要分配不同的端口

13. --tokenizer

含义:指定 tokenizer 路径,可以与模型路径不同。

默认值:使用与 --model 相同的路径。

示例:


			   bash--tokenizer /tokenizers/custom-tokenizer 

调整建议:

  • 大多数场景使用默认值即可
  • 仅在 tokenizer 与模型分离时指定

14. --quantization

含义:量化方法。

默认值:None(不使用量化)。

可选值:awqgptqsqueezellmfp8

示例:


			   bash--quantization awq --quantization fp8 

调整建议:

  • AWQ / GPTQ:适合 INT4 或 INT8 量化模型,显著降低显存占用和计算量
  • FP8:适合 H100 等支持 FP8 的 GPU,平衡精度和性能
  • 不使用量化:模型本身未量化,或对精度要求高

判断逻辑:

  • 如果模型是量化模型,必须指定对应的量化方法
  • 如果显存不足,可以考虑使用量化模型

风险提醒:

  • 量化可能影响模型输出质量,需要评估业务容忍度
  • 不同量化方法对硬件有不同要求

第三步:根据业务场景确定初始参数

场景一:实时对话服务(低延迟优先)

业务特点:

  • 输入长度:20 - 200 tokens
  • 输出长度:50 - 300 tokens
  • 并发:10 - 50 QPS
  • 延迟要求:TTFT P99 < 500ms

推荐参数:


			   bashpython -m vllm.entrypoints.openai.api_server    --model /models/llama-2-7b-chat    --dtype bfloat16    --gpu-memory-utilization 0.90    --max-model-len 2048    --max-num-seqs 256    --max-num-batched-tokens 8192    --host 0.0.0.0    --port 8000    --disable-log-requests    --trust-remote-code 

参数说明:

  • max-model-len 2048:输入输出总和通常 < 500,2048 足够,节省显存
  • max-num-seqs 256:允许高并发,降低排队时间
  • max-num-batched-tokens 8192:适中的批处理大小,平衡延迟和吞吐

场景二:长文本生成服务(吞吐量优先)

业务特点:

  • 输入长度:500 - 2000 tokens
  • 输出长度:1000 - 4000 tokens
  • 并发:5 - 20 QPS
  • 延迟容忍度:TTFT P99 < 2s

推荐参数:


			   bashpython -m vllm.entrypoints.openai.api_server    --model /models/llama-2-13b    --dtype bfloat16    --gpu-memory-utilization 0.92    --max-model-len 8192    --max-num-seqs 64    --max-num-batched-tokens 16384    --host 0.0.0.0    --port 8000    --disable-log-requests 

参数说明:

  • max-model-len 8192:支持长文本输入输出
  • max-num-seqs 64:单个请求显存占用大,降低并发数避免 OOM
  • max-num-batched-tokens 16384:更大的批处理提升吞吐量

场景三:多模型混合部署

业务特点:

  • 需要在单张 GPU 上部署 2 个不同模型
  • 每个模型独立服务,不共享显存

推荐参数:

模型 1:


			   bashpython -m vllm.entrypoints.openai.api_server    --model /models/llama-2-7b    --gpu-memory-utilization 0.45    --port 8000    --disable-log-requests 

模型 2:


			   bashpython -m vllm.entrypoints.openai.api_server    --model /models/codellama-7b    --gpu-memory-utilization 0.45    --port 8001    --disable-log-requests 

参数说明:

  • 每个模型使用 45% 显存,预留 10% 给系统和碎片
  • 不同端口避免冲突

场景四:大模型多卡推理

业务特点:

  • 模型:Llama-2-70B
  • 硬件:4 张 A100 80GB
  • 需要张量并行

推荐参数:


			   bashpython -m vllm.entrypoints.openai.api_server    --model /models/llama-2-70b    --tensor-parallel-size 4    --dtype bfloat16    --gpu-memory-utilization 0.90    --max-num-seqs 128    --host 0.0.0.0    --port 8000    --disable-log-requests 

参数说明:

  • tensor-parallel-size 4:将模型分布到 4 张 GPU
  • 其他参数与单卡类似

验证方式:


			   bashnvidia-smi 

检查 4 张 GPU 显存占用是否均衡,利用率是否接近。

第四步:启动服务并观察初始状态


			   bashpython -m vllm.entrypoints.openai.api_server    --model /models/llama-2-7b-chat    --dtype bfloat16    --gpu-memory-utilization 0.90    --max-num-seqs 256    --host 0.0.0.0    --port 8000    --disable-log-requests 

等待模型加载完成,观察以下信息:


			   INFO: Model loaded. INFO: GPU memory utilization: 0.90 INFO: Max num seqs: 256 INFO: Max model len: 4096 INFO: KV cache blocks: 12345 

关键信息:

  • KV cache blocks:可用的 KV Cache 块数,反映并发能力
  • 如果块数 < 2000,说明显存分配给 KV Cache 的空间较少,并发能力受限

检查 GPU 显存占用


			   bashnvidia-smi 

预期输出:


			   +-----------------------------------------------------------------------------+ | NVIDIA-SMI 525.125.06   Driver Version: 525.125.06   CUDA Version: 12.0   | |-------------------------------+----------------------+----------------------+ | GPU  Name        Persistence-M| Bus-Id        Disp.A | Volatile Uncorr. ECC | | Fan  Temp  Perf  Pwr:Usage/Cap|         Memory-Usage | GPU-Util  Compute M. | |                               |                      |               MIG M. | |===============================+======================+======================| |   0  NVIDIA A100-SXM...  On   | 0000000004.0 Off |                    0 | | N/A   32C    P0    58W / 400W |  36000MiB / 81920MiB |      0%      Default | |                               |                      |             Disabled | +-------------------------------+----------------------+----------------------+ 

判断逻辑:

  • 模型加载后显存占用约 36GB / 82GB = 44%
  • 剩余显存用于 KV Cache,可以支持较高并发
  • 如果显存占用 > 75GB,说明 gpu-memory-utilization 过高或模型过大

检查 metrics 接口


			   bashcurl -s http://localhost:8000/metrics | grep -E "gpu_cache|num_requests" 

预期输出:


			   vllm:gpu_cache_usage_perc{model_name="llama-2-7b-chat"} 0.0 vllm:num_requests_running{model_name="llama-2-7b-chat"} 0 vllm:num_requests_waiting{model_name="llama-2-7b-chat"} 0 

初始状态 KV Cache 使用率为 0,没有正在运行或等待的请求,符合预期。

第五步:压力测试验证参数合理性

使用压测工具模拟业务负载,观察性能指标。

准备压测脚本


			   bashcat > /tmp/load_test.py << 'EOF' import asyncio import aiohttp import time import statistics async def send_request(session, url, prompt, max_tokens):     start = time.time()     payload = {         "model""llama-2-7b-chat",         "prompt": prompt,         "max_tokens": max_tokens,         "temperature": 0.7     }     async with session.post(url, json=payload) as resp:         result = await resp.json()         duration = time.time() - start         return duration async def main():     url = "http://localhost:8000/v1/completions"     prompt = "Hello, how are you?" * 10     max_tokens = 100     concurrency = 50     total_requests = 200     async with aiohttp.ClientSession() as session:         tasks = []         for i in range(total_requests):             task = send_request(session, url, prompt, max_tokens)             tasks.append(task)             if len(tasks) >= concurrency:                 await asyncio.sleep(0.1)         latencies = await asyncio.gather(*tasks)     print(f"Total requests: {len(latencies)}")     print(f"Mean latency: {statistics.mean(latencies):.2f}s")     print(f"P50 latency: {statistics.median(latencies):.2f}s")     print(f"P90 latency: {statistics.quantiles(latencies, n=10)[8]:.2f}s")     print(f"P99 latency: {statistics.quantiles(latencies, n=100)[98]:.2f}s") if __name__ == "__main__":     asyncio.run(main()) EOF python /tmp/load_test.py 

观察监控指标

在压测过程中,实时观察:


			   bashwatch -n 1 "curl -s http://localhost:8000/metrics | grep -E 'num_requests_running|num_requests_waiting|gpu_cache_usage_perc' | grep -v '#'" 

预期输出:


			   vllm:num_requests_running{model_name="llama-2-7b-chat"} 48 vllm:num_requests_waiting{model_name="llama-2-7b-chat"} 12 vllm:gpu_cache_usage_perc{model_name="llama-2-7b-chat"} 0.65 

判断逻辑:

指标表现 结论 调整方向
num_requests_running 接近 max-num-seqs 并发已满 如果队列长,考虑调高 max-num-seqs
num_requests_running 远低于 max-num-seqs 并发未满 请求到达率低或被其他瓶颈限制
num_requests_waiting 持续 > 50 排队严重 调高 max-num-seqs 或增加副本
gpu_cache_usage_perc > 0.9 KV Cache 接近满载 降低 max-num-seqs 或调高 gpu-memory-utilization
gpu_cache_usage_perc < 0.3 KV Cache 利用率低 可能请求到达率低或输入输出较短

观察 GPU 利用率


			   bashwatch -n 1 nvidia-smi 

判断逻辑:

  • GPU 利用率 70% - 95%:正常满负载运行
  • GPU 利用率 < 50% 但队列很长:可能 CPU 瓶颈、I/O 瓶颈或批处理不合理
  • GPU 利用率 100% 且队列很长:需要扩容

第六步:根据压测结果调整参数

情况一:队列积压严重,KV Cache 使用率 < 80%

现象:


			   vllm 256 vllm 120 vllm 0.68 

分析:并发数已达上限,但 KV Cache 还有空间,可以提升并发。

调整方案:


			   bash--max-num-seqs 384 

重启服务,重新压测验证。

情况二:KV Cache 使用率 > 95%,请求被拒绝

现象:


			   vllm 256 vllm 0.97 

日志中出现:


			   WARNING: Request rejected: insufficient KV cache space 

分析:显存分配给 KV Cache 的空间不足。

调整方案:

方案一:降低并发数


			   bash--max-num-seqs 192 

方案二:提高显存使用比例(如果 GPU 上只有这一个服务)


			   bash--gpu-memory-utilization 0.95 

方案三:降低最大上下文长度(如果业务允许)


			   bash--max-model-len 2048 

情况三:TTFT 过高(P99 > 2s)

现象:


			   histogram_quantile(0.99, vllm:time_to_first_token_seconds_bucket) = 2.5s 

分析:首字延迟高,可能是批处理过大或排队严重。

调整方案:

方案一:降低批处理 token 数


			   bash--max-num-batched-tokens 4096 

方案二:降低并发数,减少排队


			   bash--max-num-seqs 128 

情况四:GPU 利用率低(< 50%)但吞吐量不足

现象:


			   GPU 利用率: 45% TPS: 30 tokens/s 队列长度: 80 

分析:GPU 算力没有充分利用,可能批处理不够大或存在其他瓶颈。

调整方案:

方案一:提高批处理 token 数


			   bash--max-num-batched-tokens 16384 

方案二:检查 CPU 瓶颈


			   bashtop -b -n 1 | grep python 

如果 CPU 使用率 > 90%,可能是 tokenization 或预处理成为瓶颈,考虑优化或增加 CPU 核心数。

方案三:检查 I/O 瓶颈


			   bashiostat -x 1 5 

如果 %util > 80%,可能是日志写入或模型加载成为瓶颈。

常用命令

查看 vLLM 版本


			   bashpython -c "import vllm; print(vllm.__version__)" 

查看模型信息


			   bashls -lh /models/llama-2-7b-chat du -sh /models/llama-2-7b-chat 

查看 vLLM 进程信息


			   bashps aux | grep vllm pstree -p $(pgrep -f vllm) 

查看启动参数(从运行中的进程)


			   bashps aux | grep vllm | grep -oP -- '--[a-z-]+ [^ ]+' | head -20 

测试推理接口


			   bashcurl http://localhost:8000/v1/models curl http://localhost:8000/v1/completions    -H "Content-Type: application/json"    -d '{     "model": "llama-2-7b-chat",     "prompt": "Hello",     "max_tokens": 50   }' | jq 

查看实时指标


			   bashwatch -n 1 "curl -s http://localhost:8000/metrics | grep -E 'num_requests_running|num_requests_waiting|gpu_cache_usage_perc|time_to_first_token' | grep -v '#'" 

配置示例

systemd 服务配置

创建 /etc/systemd/system/vllm.service:


			   ini[Unit] Description=vLLM Inference Server After=network.target [Service] Type=simple User=vllm Group=vllm WorkingDirectory=/opt/vllm Environment="CUDA_VISIBLE_DEVICES=0" ExecStart=/opt/vllm/venv/bin/python -m vllm.entrypoints.openai.api_server    --model /models/llama-2-7b-chat    --dtype bfloat16    --gpu-memory-utilization 0.90    --max-num-seqs 256    --max-model-len 4096    --host 0.0.0.0    --port 8000    --disable-log-requests Restart=always RestartSec=10 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target 

启动服务:


			   bashsystemctl daemon-reload systemctl start vllm systemctl enable vllm systemctl status vllm 

Docker Compose 配置


			   yamlversion: '3.8' services:   vllm:     image: vllm/vllm-openai:latest     container_name: vllm-server     runtime: nvidia     environment:       - NVIDIA_VISIBLE_DEVICES=0     volumes:       - /data/models:/models:ro     ports:       - "8000:8000"     command:       - --model       - /models/llama-2-7b-chat       - --dtype       - bfloat16       - --gpu-memory-utilization       - "0.90"       - --max-num-seqs       - "256"       - --max-model-len       - "4096"       - --host       - "0.0.0.0"       - --port       - "8000"       - --disable-log-requests     restart: unless-stopped     deploy:       resources:         reservations:           devices:             - driver: nvidia               count: 1               capabilities: [gpu] 

启动:


			   bashdocker-compose up -d docker-compose logs -f vllm 

Kubernetes Deployment 配置


			   yamlapiVersion: apps/v1 kind: Deployment metadata:   name: vllm-deployment   namespace: inference spec:   replicas: 2   selector:     matchLabels:       app: vllm   template:     metadata:       labels:         app: vllm     spec:       containers:       - name: vllm         image: vllm/vllm-openai:latest         args:           - --model           - /models/llama-2-7b-chat           - --dtype           - bfloat16           - --gpu-memory-utilization           - "0.90"           - --max-num-seqs           - "256"           - --max-model-len           - "4096"           - --host           - "0.0.0.0"           - --port           - "8000"           - --disable-log-requests         ports:         - containerPort: 8000           name: http         resources:           limits:             nvidia.com/gpu: 1             memory: 64Gi           requests:             nvidia.com/gpu: 1             memory: 32Gi         volumeMounts:         - name: model-storage           mountPath: /models           readOnly: true         livenessProbe:           httpGet:             path: /health             port: 8000           initialDelaySeconds: 300           periodSeconds: 30         readinessProbe:           httpGet:             path: /health             port: 8000           initialDelaySeconds: 60           periodSeconds: 10       volumes:       - name: model-storage         persistentVolumeClaim:           claimName: model-pvc --- apiVersion: v1 kind: Service metadata:   name: vllm-service   namespace: inference spec:   selector:     app: vllm   ports:   - protocol: TCP     port: 8000     targetPort: 8000   type: ClusterIP 

日志或指标观察方法

观察启动日志


			   bashjournalctl -u vllm.service -f docker logs -f vllm-container kubectl logs -f deployment/vllm -n inference 

关键日志行:


			   INFO: Model loaded. INFO: GPU memory utilization: 0.90 INFO: Max num seqs: 256 INFO: Max model len: 4096 INFO: KV cache blocks: 12345 INFO: Server started at http://0.0.0.0:8000 

观察运行时日志

如果未启用 --disable-log-requests,每个请求会产生日志:


			   INFO: Request ID: abc123, prompt_tokens: 45, completion_tokens: 120, ttft: 0.234s, total_latency: 2.456s 

统计延迟分布:


			   bashgrep "ttft:" /var/log/vllm.log | awk '{print $NF}' | sed 's/s$//' | sort -n | awk '   {     sum += $1; count++; arr[count] = $1   }   END {     print "Count:", count     print "Mean:", sum/count     print "P50:", arr[int(count*0.5)]     print "P90:", arr[int(count*0.9)]     print "P99:", arr[int(count*0.99)]   } ' 

观察错误日志


			   bashgrep -i "error|warning|failed|reject" /var/log/vllm.log docker logs vllm-container 2>&1 | grep -i "error|oom|cuda" 

常见错误:

  • CUDA out of memory:显存不足,降低 gpu-memory-utilization 或 max-num-seqs
  • Request rejected: insufficient KV cache space:KV Cache 不足,调整相关参数
  • Model loading failed:模型文件损坏或路径错误

排查路径

场景一:启动时 OOM

现象:


			   RuntimeError: CUDA out of memory. Tried to allocate X GB (GPU 0; Y GB total capacity) 

排查步骤:

  1. 检查 GPU 显存是否足够:

			   bashnvidia-smi --query-gpu=memory.total --format=csv,noheader,nounits 
  1. 估算模型所需显存:

			   模型参数量 * dtype字节数 * 1.2(额外开销) 

例如 Llama-2-7B + bfloat16:


			   7B * 2 bytes * 1.2 = 16.8 GB 
  1. 如果显存不足,调整参数:

方案一:降低显存使用比例


			   bash--gpu-memory-utilization 0.80 

方案二:使用量化模型


			   bash--quantization awq 

方案三:使用张量并行


			   bash--tensor-parallel-size 2 

场景二:队列持续积压

现象:


			   vllm 150 vllm 256 

排查步骤:

  1. 检查 KV Cache 使用率:

			   bashcurl -s http://localhost:8000/metrics | grep gpu_cache_usage_perc 
  1. 如果 KV Cache < 85%,调高 max-num-seqs:

			   bash--max-num-seqs 384 
  1. 如果 KV Cache > 95%,说明显存已满,需要扩容或降低并发

  2. 检查 GPU 利用率:


			   bashnvidia-smi 
  1. 如果 GPU 利用率 < 70%,检查 CPU、I/O 等其他瓶颈

场景三:TTFT 过高

现象:


			   histogram_quantile(0.99, vllm:time_to_first_token_seconds_bucket) > 2s 

排查步骤:

  1. 检查队列长度:

			   bashcurl -s http://localhost:8000/metrics | grep num_requests_waiting 

如果队列长,说明排队时间长,需要提升并发能力或增加副本。

  1. 检查批处理 token 数:

			   bashps aux | grep vllm | grep max-num-batched-tokens 

如果过大,考虑降低:


			   bash--max-num-batched-tokens 4096 
  1. 检查输入长度分布:

			   bashgrep "prompt_tokens" /var/log/vllm.log | awk '{print $4}' | sort -n | uniq -c 

如果输入普遍很长,TTFT 高是正常现象。

场景四:TPS 不达预期

现象:


			   sum(rate(vllm:generation_tokens_total[5m])) < 50 

排查步骤:

  1. 检查 GPU 利用率:

			   bashnvidia-smi 
  1. 如果 GPU 利用率 < 70%,检查批处理参数:

			   bash--max-num-batched-tokens 16384 
  1. 检查 GPU 是否降频:

			   bashnvidia-smi --query-gpu=clocks.current.graphics,clocks.max.graphics --format=csv 
  1. 检查是否使用了不合适的 dtype:

			   bashps aux | grep vllm | grep dtype 

如果使用 float32,改为 bfloat16 或 float16。

风险提醒

1. 参数调整导致服务不可用

高风险操作:

  • 修改 max-num-seqsgpu-memory-utilization 后重启服务
  • 修改 tensor-parallel-size 后无法启动

操作前检查:

  • 备份当前配置
  • 在测试环境验证
  • 准备回滚方案

2. 显存配置不当导致 OOM

风险场景:

  • gpu-memory-utilization 设置过高(> 0.98)
  • max-num-seqs 设置过高
  • max-model-len 设置过高

预防措施:

  • 逐步调高参数,每次调整后压测验证
  • 监控 GPU 显存使用率,避免超过 95%

3. 并发参数调整导致性能下降

风险场景:

  • max-num-seqs 调整过高,KV Cache 不足,请求被拒绝
  • max-num-batched-tokens 调整过低,GPU 利用率下降

预防措施:

  • 每次调整后观察 KV Cache 使用率、GPU 利用率、队列长度
  • 压测验证 TTFT 和 TPS 是否符合预期

4. 多副本部署端口冲突

风险场景:

  • 在同一机器上启动多个 vLLM 实例,端口冲突导致启动失败

预防措施:

  • 为每个实例分配不同端口
  • 使用 systemd 或 docker-compose 管理,避免手动启动时遗漏参数

验证方式

验证参数是否生效

启动后检查日志:


			   bashjournalctl -u vllm.service | grep "Max num seqs|GPU memory utilization|Max model len" 

预期输出:


			   INFO: Max num seqs: 256 INFO: GPU memory utilization: 0.90 INFO: Max model len: 4096 

验证并发能力

发送并发请求,观察有多少请求同时运行:


			   bashfor i in {1..300}; do   curl -s http://localhost:8000/v1/completions      -H "Content-Type: application/json"      -d '{"model":"llama-2-7b","prompt":"Test","max_tokens":50}' & done sleep 2 curl -s http://localhost:8000/metrics | grep num_requests_running 

预期输出:


			   vllm:num_requests_running{model_name="llama-2-7b"} 256 

如果等于或接近 max-num-seqs,说明参数生效。

验证显存占用


			   bashnvidia-smi --query-gpu=memory.used,memory.total --format=csv,noheader,nounits curl -s http://localhost:8000/metrics | grep gpu_cache_usage_perc 

计算显存使用率:


			   显存使用率 = memory.used / memory.total 

应接近 gpu-memory-utilization 设置值。

回滚方案

systemd 服务回滚


			   bashcp /etc/systemd/system/vllm.service /etc/systemd/system/vllm.service.backup vi /etc/systemd/system/vllm.service systemctl daemon-reload systemctl restart vllm systemctl status vllm 

Docker Compose 回滚


			   bashcp docker-compose.yml docker-compose.yml.backup vi docker-compose.yml docker-compose down docker-compose up -d docker-compose logs -f vllm 

Kubernetes 回滚


			   bashkubectl rollout undo deployment/vllm-deployment -n inference kubectl rollout status deployment/vllm-deployment -n inference 

生产环境注意事项

1. 参数变更流程

生产环境参数变更应遵循以下流程:

  1. 在测试环境验证
  2. 准备回滚方案
  3. 选择低峰期变更
  4. 逐个副本变更,观察效果
  5. 变更后持续观察 24 小时

2. 配置文件管理

  • 将启动参数写入配置文件,而不是命令行
  • 使用版本控制管理配置文件
  • 每次变更前备份当前配置

示例配置文件 /etc/vllm/config.json:


			   json{   "model": "/models/llama-2-7b-chat",   "dtype": "bfloat16",   "gpu_memory_utilization": 0.90,   "max_num_seqs": 256,   "max_model_len": 4096,   "host": "0.0.0.0",   "port": 8000,   "disable_log_requests": true } 

启动时加载:


			   bashpython -m vllm.entrypoints.openai.api_server --config /etc/vllm/config.json 

(注意:vLLM 可能不支持 JSON 配置文件,需要将配置转换为命令行参数)

3. 多副本部署策略

生产环境建议部署多个副本,提升可用性和吞吐量。

负载均衡配置(Nginx):


			   nginxupstream vllm_backend {     least_conn;     server 192.168.1.101:8000 max_fails=3 fail_timeout=30s;     server 192.168.1.102:8000 max_fails=3 fail_timeout=30s;     server 192.168.1.103:8000 max_fails=3 fail_timeout=30s; } server {     listen 80;     server_name vllm.example.com;     location / {         proxy_pass http://vllm_backend;         proxy_http_version 1.1;         proxy_set_header Connection "";         proxy_set_header Host $host;         proxy_set_header X-Real-IP $remote_addr;         proxy_read_timeout 300s;     } } 

4. 灰度发布

参数变更时,先在部分副本上变更,观察效果后再全量发布。


			   bashkubectl set image deployment/vllm-deployment vllm=vllm/vllm-openai:new-config -n inference kubectl rollout pause deployment/vllm-deployment -n inference # 观察 10 分钟 kubectl rollout resume deployment/vllm-deployment -n inference 

5. 参数调优迭代

参数调优是一个持续迭代的过程:

  1. 初始部署:使用推荐的默认参数
  2. 收集1周数据:输入输出长度分布、并发峰值、延迟分布
  3. 第一次调优:根据数据调整 max-num-seqsmax-model-len
  4. 观察2周:验证调整效果,收集新数据
  5. 第二次调优:微调 gpu-memory-utilizationmax-num-batched-tokens
  6. 持续监控:定期回顾指标,根据业务变化调整

6. 文档和知识沉淀

  • 记录每次参数调整的原因、过程、结果
  • 形成参数调优决策树,便于后续参考
  • 定期培训团队成员,确保每个人都理解参数含义

7. 告警配置

为关键参数配置告警:

  • KV Cache 使用率 > 90%
  • 队列长度 > 100 持续 5 分钟
  • GPU 显存使用率 > 95%
  • TTFT P99 超过业务阈值

8. 成本优化

在满足性能要求的前提下,优化资源使用:

  • 降低 max-model-len 节省显存
  • 使用量化模型降低计算和显存开销
  • 根据业务低峰期动态调整副本数

9. 安全和权限

  • 限制 --trust-remote-code 的使用,仅在必要时启用
  • API 接口配置认证和限流,避免滥用
  • 模型文件权限设置为只读,避免被篡改

10. 监控和可观测性

  • 部署 Prometheus + Grafana 监控
  • 配置链路追踪,关联请求 ID
  • 保留足够的日志和指标数据用于回溯分析

总结

vLLM 启动参数的调整是一个基于业务特点和硬件环境的定制化过程。核心要点包括:

  1. 理解参数含义:每个参数都对应推理流程中的某个环节,理解其作用才能合理调整

  2. 明确业务特点:输入输出长度、并发模式、延迟要求决定了参数配置方向

  3. 从默认值开始:默认参数适合大多数场景,先观察瓶颈再调整

  4. 逐个调整验证:每次只调整一个参数,避免多参数叠加难以定位问题

  5. 关键参数:gpu-memory-utilizationmax-num-seqsmax-model-len 是最核心的调优参数

  6. 权衡取舍:显存、延迟、吞吐量之间需要权衡,没有完美的配置

  7. 持续优化:随着业务发展和数据积累,参数配置需要持续调整

  8. 风险管控:参数变更可能导致服务不可用,需要测试、备份、灰度发布

在实际操作中,参数调优不是一劳永逸的,需要结合监控数据和业务反馈持续迭代。同时,参数配置应该文档化、版本化,避免人为失误和知识流失。

最后,参数调优的目标是在满足业务需求的前提下,最大化资源利用效率。不要盲目追求极致性能,而忽略了稳定性和可维护性。一个稳定、可预测、易于调试的系统,比一个性能极致但脆弱的系统更有价值。

 


打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分