Day14 | vLLM——把训完的模型搬上线的“印钞机“

发布时间:2026/7/6 7:11:27

Day14 | vLLM——把训完的模型搬上线的“印钞机“ 苦猿的大模型日记 · Day14 · vLLM——把训完的模型搬上线的印钞机-帮普通人把AI学进简历系列前言模型训完了发上去一推理你傻了你刚把一个 GRPO 训完的 reasoning 模型权重 push 到服务器满怀激动地用 transformers 起了个 FastAPI 服务发了个测试请求——8 秒。一条请求 8 秒。你以为网络卡了又发一条。还是 8 秒。你寻思可能并发能好点开了 10 个并发一起打。显卡直接OOM。你盯着nvidia-smi那条上蹿下跳的曲线发呆——A100一张一天 800 块钱的卡GPU 利用率 8%。老板这时候路过你工位问了一句你这辈子都不想听的话「这卡的钱公司能报销吗」那一刻我才明白一个事——训完一个模型离它能上线中间还隔着一整座山。我当年卡在这座山上卡了大半年。后来遇到一个工具把吞吐量干到了原来的二十多倍——它叫 vLLM。今天我把它讲透。PART 01transformers 起服务——你以为能用其实是老头乐很多人觉得模型推理嘛不就是model.generate()加一层 FastAPI 包一下我先把这套原始方案的代码贴出来你看看眼熟不眼熟——from fastapi import FastAPI from transformers import AutoModelForCausalLM, AutoTokenizer app FastAPI() model AutoModelForCausalLM.from_pretrained( Qwen/Qwen3-8B-Instruct, device_mapauto, torch_dtypeauto, ) tokenizer AutoTokenizer.from_pretrained(Qwen/Qwen3-8B-Instruct) app.post(/chat) def chat(prompt: str): inputs tokenizer(prompt, return_tensorspt).to(cuda) output model.generate(**inputs, max_new_tokens512) return {response: tokenizer.decode(output[0])}跑起来单条请求是能出结果的。但你只要往上面压并发三个致命问题立刻爆出来——第一个毛病逐 token 生成没有批处理意识。transformers 的generate()是一个完整的端到端调用进来一个请求就生成完才放你走。第二个请求来了对不起排队。你的显卡里其实 99% 的算力在睡大觉。第二个毛病KV cache 一次性占用10 个并发就 OOM。LLM 推理时每生成一个 token 都要回头查前面所有 token 的 Key/Value 中间状态——这就是KV cache。问题在于transformers 给每个请求预分配一整块连续显存按最长可能长度算。你 8B 模型max length 8192一个请求就能吃掉 6GB 显存。10 个并发一起进来A100 80GB 都扛不住。第三个毛病GPU 利用率个位数。不是显卡不行是算法层就没为推理优化。transformers 是为训练设计的不是为 serving 设计的。你拿它做推理等于拿超跑去送外卖——一次送一份还堵在路口。下面这张图是我自己实测的同样一张 A100、同一个 Qwen3-8B——方案单卡 QPSGPU 利用率transformers FastAPI~38%vLLM**~75****92%**24 倍。不是优化几个点的事是数量级的差距。那 vLLM 到底干了什么PART 02vLLM 的印钞机原理——PagedAttention Continuous BatchingvLLM 是 2023 年 UC Berkeley 发的论文标题就一个词——Efficient Memory Management for Large Language Model Serving with PagedAttention。但说实话论文那套术语我看着都头大。我用大白话给你翻译一下——vLLM 的核心就两件事把显存榨干把批处理做活。第一件PagedAttention——把显存从包场改成按需点菜传统 KV cache 的问题一句话——给每个请求包场不管它坐不坐得满。一个请求声明 我可能要 8192 个 token显存就真给它留 8192 个位置。最后它可能只生成了 800 个 token剩下 7000 多个位置白白占着。PagedAttention 干的事你可以类比成操作系统的虚拟内存——把 KV cache 切成固定大小的 block比如每 16 个 token 一块按需分配。你要 800 token好给你 50 个 block。你要 8192好给你 512 个 block。不够再补。而且这些 block 在物理显存里可以不连续靠一张映射表串起来。这一个改动显存利用率从 ~30% 拉到 ~95%。同样是 80GB 显存能塞下的并发请求数直接翻了三倍。第二件Continuous Batching——批处理不再队头阻塞传统 batching 的逻辑是——一批 8 个请求同时进来等最慢那个生成完才能进下一批。第一个请求 50 token 就答完了最后一个要生成 800 token——前面那位得在显存里干等。Continuous Batching 的逻辑是——每一个生成步step都重新组 batch。谁生成完了立刻走人新请求立刻补进来。传统批处理 [A B C D] ────────────► 全部结束下一批 ↑ 队头阻塞 连续批处理 [A B C D] [A B C _] ← D 结束走人E 加入 [A B C E] [_ B C E] ← A 也走了F 来了 [F B C E]每一步 GPU 都在满负荷干活没有一个 token 在干等。这一个改动吞吐量再提 8-14 倍。两件事叠在一起就是开头那张表里24 倍的来源。到这里你大概明白了——vLLM 不是什么小优化是把推理这件事重新设计了一遍。那实战怎么用下面 5 分钟带你跑起来。PART 035 分钟把模型跑起来——vLLM 实操vLLM 的设计哲学很粗暴——一行命令起服务。第一步安装pip install vllm注意 vLLM 只支持 LinuxWindows 用户得用 WSL2 或者直接租 Linux 服务器。第二步一行 CLI 启动服务vllm serve Qwen/Qwen3-8B-Instruct \ --gpu-memory-utilization 0.9 \ --max-model-len 8192 \ --tensor-parallel-size 1 \ --enable-prefix-caching启动完你会在终端看到一行INFO: Uvicorn running on http://0.0.0.0:8000服务就起来了对外暴露的是 OpenAI 兼容 API——这意味着你之前调 OpenAI 的代码把base_url改一下就能直接用。第三步客户端调用curl 版本curl http://localhost:8000/v1/chat/completions \ -H Content-Type: application/json \ -d { model: Qwen/Qwen3-8B-Instruct, messages: [{role: user, content: 你好介绍一下你自己}] }Python 用 OpenAI SDK 版本最推荐from openai import OpenAI client OpenAI( base_urlhttp://localhost:8000/v1, api_keydummy, # vLLM 本地不校验 key ) resp client.chat.completions.create( modelQwen/Qwen3-8B-Instruct, messages[{role: user, content: 用一句话解释 PagedAttention}], ) print(resp.choices[0].message.content)跑通之后你再去nvidia-smi看一眼——GPU 利用率从 8% 直接拉到 90%。关键参数怎么调不是流水账这四个参数你必须懂不懂就是面试必挂——--gpu-memory-utilizationvLLM 能用多少显存。默认 0.9意思是这张卡的 90% 给我。显存够就拉到 0.95吞吐还能再涨一截显存紧张机器上还跑别的任务就降到 0.7。我一般直接拉满。--max-model-len模型最大上下文长度。越大越吃显存——KV cache 是按这个长度预计算的。Qwen3-8B 默认支持 32K但你 RAG 场景真用得到 32K 吗大部分场景8192 足够砍一半显存能多塞一倍并发。--tensor-parallel-size多卡切分。TP2 就是把模型横切两半一张卡存一半权重。只有当单卡塞不下整个模型时才用——单卡能塞下就别开TP 通信开销反而拖慢速度。--enable-prefix-caching相同前缀共享 KV。这个我建议你无脑开。RAG 场景里几十条 query 都引用同一份文档那份文档的 KV cache 第一次算完之后所有后续请求直接复用——延迟砍一半吞吐翻倍。Agent 工具调用场景同理system prompt 是固定的能省一大笔。参数讲完下一个问题——怎么知道你的服务真的调好了得压测。PART 04压测与调优——同样的卡吞吐差 3 倍vLLM 自带一个压测脚本路径在vllm/benchmarks/benchmark_throughput.py。直接跑python -m vllm.benchmarks.benchmark_throughput \ --model Qwen/Qwen3-8B-Instruct \ --backend vllm \ --num-prompts 1000 \ --request-rate 10输出会告诉你平均每个请求的延迟和整体吞吐量。你该盯的三个信号信号 1GPU 显存利用率。nvidia-smi持续高位90%才是好事。如果只有 40%说明 vLLM 没吃饱——大概率是gpu-memory-utilization调低了或者请求 QPS 不够。信号 2请求延迟分布P50 / P99。P99 飙高说明有请求在排队。要么是 batch 满了要么是 max-model-len 设太短导致频繁截断重算。信号 3KV cache 命中率。开了 prefix caching 之后vLLM 日志会打印cache hit rate。低于 30% 说明你的请求前缀不够集中——RAG 场景低于这个数检查一下 system prompt 是不是每个请求都不一样。调优经验表实测不是 GPT 编的场景调什么为什么显存够想榨吞吐--gpu-memory-utilization 0.95留 5% 给临时计算就够再多就是浪费显存紧张 OOM砍 --max-model-len别砍 batch砍 batch 会让 continuous batching 失效长 prompt RAG必开 --enable-prefix-caching共享文档 KV延迟减半多卡机器优先 TP不要 DPDP 要自己写调度器vLLM 的 TP 是开箱即用高并发短输出调高 --max-num-seqsbatch size 上限默认 256可以拉到 512调到一份能跑出75 QPS / P99 800ms的配置A100 单卡Qwen3-8B——这就够交付大部分在线场景了。但有个事我得提醒你——vLLM 不是万能的。PART 05什么场景该用 vLLM什么场景别用我跟你说实话——vLLM 解决的是高并发在线服务问题不是所有推理场景都该上它。这些场景vLLM 是真神1. 在线 chat / API 服务——多用户高并发吞吐量直接关系到成本。2. RAG 系统——长 prompt、固定文档前缀prefix caching 直接起飞。3. Agent / Function Calling——system prompt 长、tool 描述固定每次调用复用 KV。4. 批量推理任务——一晚上跑完几十万条数据continuous batching 让你提前下班。这些场景别用 vLLM1. 单用户本地玩。你只是想在自己笔记本上跑个模型玩玩——用 Ollama不要用 vLLM。vLLM 是为多并发设计的单用户场景它的优势完全用不上反而吃满你显存。2. 极致延迟敏感单请求 100ms。vLLM 优化的是吞吐量不是单请求延迟。如果你做的是同声传译、实时语音这种 100ms 内必须出第一个 token 的场景vLLM 反而不一定比 transformers 快——因为它要组 batch会有几毫秒的等待。3. 自定义架构 / 非标准注意力。vLLM 支持的模型有列表GitHub 上一个models.md你的模型如果改了 attention 结构比如自定义的 sparse attentionvLLM 大概率不认——这时候只能 transformers 自己起。一个最常被问到的误区「vLLM 和量化啥关系是不是开了 vLLM 模型就变小了」不是。量化是把模型权重从 fp16 压成 int8/int4用 AWQ、GPTQ 这些工具目的是让模型本身变小。vLLM 是个推理服务框架负责把模型高效地跑起来——你给它什么精度的模型它就跑什么精度。两者的关系是叠加不是替代——你可以给 vLLM 喂一个 AWQ 量化过的模型显存占用再砍一半吞吐量再翻一倍。vllm serve TheBloke/Qwen3-8B-Instruct-AWQ \ --quantization awq \ --gpu-memory-utilization 0.9到这里 vLLM 讲得差不多了。最后我给你留一个判断——结尾训完的模型不上线等于没训我见过太多团队卡在这一步——SFT 跑通了对齐跑通了权重也存好了然后扔在硬盘里三个月没人上线。为什么因为上线推一把发现 A100 烧不起。训出来的模型不会自己跑到生产环境。得有人把它背上去——选好框架、调好参数、压测、监控、扩容。vLLM 就是那把背篓。我自己的体感是——SFT 决定你的模型有多聪明vLLM 决定它能在几张卡上聪明得下去。前一件大家都在卷论文一周一篇后一件没人在意但它是真烧钱。一张 A100 一天 800 块调好 vLLM 一年能给公司省一套首付。这种活老板不会单独派给你——你得自己懂、自己上、自己认领。这就是简历上模型推理优化经验那一行的来源。下一篇我们继续——上线的模型跑得慢到底怎么定位瓶颈是 GPU 算力不够、还是 IO 卡了、还是请求 pattern 有问题我们聊LLM 推理性能分析。— END —苦猿 · 帮普通人把 AI 学进简历

相关新闻