vLLM推理加速指南:7个技巧让QPS提升30-60%

本文涉及的产品
实时计算 Flink 版,1000CU*H 3个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
实时数仓Hologres,5000CU*H 100GB 3个月
简介: GPU资源有限,提升推理效率需多管齐下。本文分享vLLM实战调优七招:请求塑形、KV缓存复用、推测解码、量化、并行策略、准入控制与预热监控。结合代码与数据,助你最大化吞吐、降低延迟,实现高QPS稳定服务。

GPU 永远不够用,这大概是每个做推理服务的人都有的共识。相比无脑加卡,更实际的办法是把现有资源榨干。下面这些是我在实际项目里反复用到的几个调优手段,有代码、有数据、也有一些踩坑经验。

1

1、连续批处理的请求塑形

vLLM 的核心优势在于 continuous batching,把多个请求的 token 打包进同一个计算步骤。想要发挥这个特性,需要在请求端做些配合。

max_new_tokens 必须要控制,对于聊天场景 256 到 512 基本够用。那种动不动要生成几千 token 的请求会拖垮整个 batch 的效率。流式返回可以降低用户感知到的延迟,同时让 batch 持续运转。另外 prompt 长度如果能相对统一会更好,长短差异太大会影响 packing 效率。

客户端可以这样写,异步流式加并发控制:

import asyncio  
from openai import AsyncOpenAI  

client = AsyncOpenAI(base_url="http://localhost:8000/v1", api_key="NOT_NEEDED")  

SEM = asyncio.Semaphore(128)  # tune: concurrent in-flight requests  

async def ask(msg: str):  
    async with SEM:  
        stream = await client.chat.completions.create(  
            model="your-vllm-model",  
            messages=[{"role":"system","content":"You are concise."},  
                      {"role":"user","content":msg}],  
            temperature=0.7,  
            max_tokens=256,   # keep it bounded  
            stream=True  
        )  
        out = []  
        async for chunk in stream:  
            token = chunk.choices[0].delta.content or ""  
            out.append(token)  
        return "".join(out)  

async def main():  
    qs = [f"Question {i}" for i in range(500)]  
    answers = await asyncio.gather(*[ask(q) for q in qs])  
    print(answers[0])  

asyncio.run(main())

这种模式能让服务端持续收到短小可控的生成请求,continuous batching 的效果就出来了。

2、KV cache 复用的前缀设计

vLLM 的 paged attention 和 KV cache reuse 机制要求共享前缀在字节级别完全一致。所以system prompt一定要固定下来,连标点和空格都别改。动态内容往后放,用户数据、工具输出这些全部挪到消息末尾。

template 里千万别在用户问题前面插时间戳或者随机 ID,cache miss 率会飙升。

SYSTEM = (  
    "You are a helpful assistant. Use bullet points. "  
    "Cite numbers when you can.\n"  # stable, byte-for-byte  
)  

def build_messages(user_msg: str, hints: list[str]):  
    # Put variable hints AFTER the user message to maximize shared prefix.  
    return [  
        {"role": "system", "content": SYSTEM},  
        {"role": "user", "content": user_msg + "\n\n" + "\n".join(hints)},  
    ]

FAQ 类应用或者 RAG 场景下,这招的收益非常明显,QPS 能有肉眼可见的提升。

3、推测解码配小模型

GPU 预算紧张的时候,speculative decoding 值得一试。小模型先提议 token,大模型负责验证,整体步数能减少不少。

拿个 1B 到 8B 的小模型做 draft,配合主模型使用。在 temperature 0.3 到 0.9 这个区间、中等长度输出的场景效果最好。acceptance rate 健康的话,tokens/sec 会有实打实的增长。

# e.g., vLLM server args  
--model main-model  
--speculative-draft-model tiny-draft-model

需要盯着 acceptance rate、draft 模型的显存占用,以及那些特别有创意的生成场景(draft 在这种情况下帮助有限)。

4、量化来换 batch size

权重量化能在同样的显卡上跑更大的 batch。AWQ 和 GPTQ 这类方法在聊天质量上的损失相对可控,比简单粗暴地全面 4-bit 要好。但不是所有模型都适合激进量化,有些架构压过头会丢失语言风格或者逻辑连贯性。

量化完重新调 batch 上限,通常能塞进去更多并发序列,QPS 自然就上来了。经验上讲,显存卡住计算之前成为瓶颈的话,量化是最该是最先考虑的。

5、拓扑匹配的并行策略

多卡机器上,tensor parallel size 要和模型用的 GPU 数量对齐,进程要 pin 住。

单模型多卡就用 tensor parallelism,让每张卡分摊模型的一部分并且每步都参与计算。

一台机器跑多个模型的话,进程隔离更合适,内存带宽和上下文切换会严重拖累 QPS。CPU pinning 和 GPU affinity 别偷懒,让数据加载和网络线程尽量靠近设备。

运维上还有几个点要注意:数据中心的 GPU 关掉节能模式;显存利用率控制在 90% 到 95%,给突发流量留点余量;多个 vLLM 实例记得分配独立的端口和 GPU(比如 CUDA_VISIBLE_DEVICES=0,12,3 分开)。

6、准入控制保护批处理引擎

高 QPS 不光是吞吐,还要在高负载下保持稳定。在 vLLM 前面加一层简单的门控来过滤请求。

超过 max tokens 或者 timeout 预算的请求直接拒掉或者降级处理。每个 API key 用 leaky bucket 或者 token bucket 限流。队列最好带 backpressure,避免超时堆积导致雪崩。

from fastapi import FastAPI, HTTPException, Request  
import asyncio, time  

app = FastAPI()  
SEM = asyncio.Semaphore(256)     # max in-flight  
MAX_NEW_TOKENS = 384  
REQ_TIMEOUT_S = 20  

@app.middleware("http")  
async def guard(request: Request, call_next):  
    start = time.time()  
    params = await request.json() if request.method == "POST" else {}  
    if params.get("max_tokens", MAX_NEW_TOKENS) > MAX_NEW_TOKENS:  
        raise HTTPException(400, "max_tokens too large")  
    try:  
        async with asyncio.timeout(REQ_TIMEOUT_S):  
            async with SEM:  
                response = await call_next(request)  
                return response  
    except TimeoutError:  
        raise HTTPException(503, "Busy, try lower max_tokens")  
    finally:  
        # you can log (queue_depth, wait_ms, in_flight) here  
        pass

这个代码看着很简单但是用起来的话是真管用,可以防止少数贪婪请求把所有人的延迟都拉垮。

7、热路径预热和指标监控

还有两个看起来无聊但实际很关键的点。

第一是预热。部署的时候先用合成请求把常用的 system prompt 和 template 跑几遍,让 KV cache pages 提前填充好。5 到 10 个请求就够,能让第一分钟的性能稳下来。

import asyncio  
HOT_PROMPTS = [  
    "Summarize this email in 3 bullets:",  
    "Draft a polite reply:",  
    "Explain this code block step-by-step:"  
]  

async def warm():  
    await asyncio.gather(*[ask(p) for p in HOT_PROMPTS for _ in range(3)])  

# call warm() right after deploy; ignore outputs

第二是监控指标别弄错了,generated tokens/sec 是 QPS 的核心指标,scheduler queue length 告诉你什么时候该扩容或者甩负载。平均值有时候没什么太大的用处,所以p50/p95/p99 的 time-to-first-token 和 time-to-last-token 才反映真实体验,产品质量活在 p95。

整体流程

最后整理一个完整的流程:

请求先到 FastAPI 的门控层,限制 max_tokens 和并发数,短暂排队后批量打到 vLLM 进程(绑定了特定 GPU)。vLLM 用 paged attention 管理多个序列,持续批处理新 token。稳定前缀命中 KV cache,speculative decoding 减少步骤,量化权重控制显存。token 流式返回,队列深度超阈值就开始丢弃低优先级流量。

总结

在最后总结之前先给一个实测的数据

单张 80GB 的 GPU 跑 7B 到 8B 的聊天模型,从无限制无流式改成流式加 256 token 上限,用户感知响应速度能翻倍,可持续 QPS 提升 30% 到 60%,能提高这么多的主要原因就是因为 batch 健康了。

而且配置合理的 speculative setup 能再加 15% 到 35% 的 tokens/sec,但是这个具体要看模型。上面说的前缀复用如果做得好,FAQ 场景基本就是开挂,基本能提高1倍多。

vLLM 上跑高 QPS 不能从单点突破,而是需要多个优化叠加才能产生好的结果。从请求塑形开始,把能复用的缓存用上,再叠加 speculative decoding 和量化。后面用并行和准入控制保证规模化的稳定性,热路径预热,盯住真正能反映问题的指标。

https://avoid.overfit.cn/post/fe3bc408622e424695dbcc27f0b7f14f

作者:Syntal

目录
相关文章
|
10天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!
|
9天前
|
存储 人工智能 Java
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
本文讲解 Prompt 基本概念与 10 个优化技巧,结合学术分析 AI 应用的需求分析、设计方案,介绍 Spring AI 中 ChatClient 及 Advisors 的使用。
401 130
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
|
3天前
|
存储 安全 前端开发
如何将加密和解密函数应用到实际项目中?
如何将加密和解密函数应用到实际项目中?
197 138
|
9天前
|
人工智能 Java API
AI 超级智能体全栈项目阶段一:AI大模型概述、选型、项目初始化以及基于阿里云灵积模型 Qwen-Plus实现模型接入四种方式(SDK/HTTP/SpringAI/langchain4j)
本文介绍AI大模型的核心概念、分类及开发者学习路径,重点讲解如何选择与接入大模型。项目基于Spring Boot,使用阿里云灵积模型(Qwen-Plus),对比SDK、HTTP、Spring AI和LangChain4j四种接入方式,助力开发者高效构建AI应用。
376 122
AI 超级智能体全栈项目阶段一:AI大模型概述、选型、项目初始化以及基于阿里云灵积模型 Qwen-Plus实现模型接入四种方式(SDK/HTTP/SpringAI/langchain4j)
|
3天前
|
存储 JSON 安全
加密和解密函数的具体实现代码
加密和解密函数的具体实现代码
196 136
|
21天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1347 8
|
8天前
|
监控 JavaScript Java
基于大模型技术的反欺诈知识问答系统
随着互联网与金融科技发展,网络欺诈频发,构建高效反欺诈平台成为迫切需求。本文基于Java、Vue.js、Spring Boot与MySQL技术,设计实现集欺诈识别、宣传教育、用户互动于一体的反欺诈系统,提升公众防范意识,助力企业合规与用户权益保护。
|
20天前
|
机器学习/深度学习 人工智能 前端开发
通义DeepResearch全面开源!同步分享可落地的高阶Agent构建方法论
通义研究团队开源发布通义 DeepResearch —— 首个在性能上可与 OpenAI DeepResearch 相媲美、并在多项权威基准测试中取得领先表现的全开源 Web Agent。
1455 87