LLM 推理部署优化实战:vLLM、TGI 与 TensorRT-LLM 选型与调优

LLM 推理部署优化实战:vLLM、TGI 与 TensorRT-LLM 选型与调优

一、同一个模型,4 张卡 vs 1 张卡

先讲一个真实的对比。早期用 HuggingFace Transformers + A100 4 卡部署一个 13B 模型:吞吐量每卡 5 QPS 共 20 QPS,延迟 P99 约 800ms,显存占用每张 60GB,月成本约 6 万元。换成 vLLM + A100 1 卡之后:吞吐量 80 QPS(提升 4 倍),延迟 P99 降到 200ms,显存占用 20GB,月成本降到 1.5 万元。

这个对比说明一个核心观点:LLM 推理优化是 ROI 最高的工程活。同样的硬件,选对引擎、做好配置,吞吐量可以差 4-10 倍。在模型能力过剩、成本吃紧的今天,谁把推理压得又便宜又快,谁就掌握部署的主动权。

二、推理的核心瓶颈在哪

LLM 推理分两个阶段。Prefill(预填充)阶段并行计算所有输入 token,属于计算密集,瓶颈在 GPU 算力,优化方向是张量并行。Decode(解码)阶段逐 token 生成,每次新增一个 token 都要读一遍全部历史 KV Cache,属于访存密集,瓶颈在显存带宽。两个阶段特性完全不同,优化手段也不同。

三个核心瓶颈值得记住:

瓶颈一:KV Cache 占显存。KV Cache 大小约为 2 × 层数 × 头数 × 头维度 × 序列长度 × batch × 2 字节。13B 模型在 2048 序列、batch 10 时约需 16.8GB——这往往是比模型权重更占显存的部分。

瓶颈二:Decode 阶段每生成一个 token 都要读全量 KV。显存带宽成为瓶颈。H100 是 3.35 TB/s,A100 是 2 TB/s,算力再高也绕不过这条带宽墙。

瓶颈三:请求长度差异大。短请求(10 token)和长请求(2000 token)混在一起,静态批处理下 GPU 利用率不均,短请求被长请求拖累。

三、vLLM:当前最主流的推理框架

vLLM 的核心创新是 PagedAttention——借鉴操作系统虚拟内存的分页机制管理 KV Cache。传统方法按最大序列长度预分配连续显存,实际利用率往往只有 30%;分页后按需分配、离散存储、页表映射,显存利用率可以拉到 95%,同等显存下吞吐量提升 2-4 倍。

除了 PagedAttention,vLLM 还集成了几个关键优化:Continuous Batching(请求随时插队,不用等整批结束)、Chunked Prefill(长输入分块,避免阻塞短请求)、Speculative Decoding(小模型预生成大模型验证,加速约 2 倍)、量化(INT8/INT4 降显存)、Tensor Parallel(多卡拆分模型)。

部署一个 OpenAI 兼容服务非常简单:

pipinstallvllm python-mvllm.entrypoints.openai.api_server\--modelQwen/Qwen2.5-7B-Instruct\--tensor-parallel-size1\--gpu-memory-utilization0.9\--max-model-len4096\--port8000```调用方直接用 OpenAI SDK,把 base_url 指向本地端口即可,业务代码零改动。这也是 vLLM 生态快速扩张的重要原因——换引擎不换接口。 高级配置:量化推理用`--quantization awq`;投机解码用`--speculative-model`加小模型并指定`--num-speculative-tokens5`;多 LoRA 用`--enable-lora --lora-modules`实现一个服务承载多个业务适配器。## 四、TGI 与 TensorRT-LLM:另外两条路线**TGI(Text Generation Inference)** 是 HuggingFace 的工业级方案,Rust 实现、内置 Prometheus 指标、Docker 一键部署,支持 FlashAttention、GPTQ、AWQ 量化。适合运维省心的团队。缺点是性能略逊于 vLLM,多 LoRA 支持一般。 **TensorRT-LLM** 是 NVIDIA 官方的推理优化器,编译期做算子融合和调度优化,支持比 Continuous Batching 更激进的 Inflight Batching,量化支持 FP8/INT8/INT4。性能比 vLLM 高15-20%,但部署门槛高得多——需要先编译模型引擎再启动服务。适合追求极致性能、有专门工程团队的场景。 性能对比参考(A100 80GB 单卡、Qwen 7B):Transformers5QPS/800ms;vLLM80QPS/200ms;TGI70QPS/230ms;TensorRT-LLM95QPS/180ms。 选型建议:性能优先选 vLLM;运维省心选 TGI;极致性能选 TensorRT-LLM;需要频繁切换 LoRA 选 vLLM。## 五、量化:用精度换显存的性价比之选量化的本质是把权重从高精度(FP16)压到低比特。对比:FP16 基线,INT8 模型减半、精度损失小于1%;INT4(AWQ/GPTQ)模型缩到1/4,精度损失1-3%;FP8 减半且几乎无损,但需要 H100 等新硬件。 选型建议:通用场景 AWQ INT4 性价比最高;极低显存环境用 BnB INT4;H100 硬件用 FP8。量化不是免费的午餐,数学推理、长文本理解、代码生成这类精度敏感任务,退化幅度可能超出预期,上线前务必在目标任务真实评测集上对比原模型。## 六、进一步加速:投机解码与前缀缓存投机解码用一个小模型快速生成候选 token,大模型一次性并行验证5个 token,接受匹配的、拒绝不匹配的重新生成,平均加速2-3 倍。前提是小模型猜得准,猜错太多反而拖后腿,建议在自己的数据集上实测。 前缀缓存(Prefix Caching)针对"多个请求共享系统提示"的场景——比如相同的翻译指令、相同的角色设定占了1000token,这部分 KV Cache 可以复用,省掉大量重复的预填充计算。vLLM 用`--enable-prefix-caching`开启。## 七、部署实战工作流:从模型到服务一个可复制的部署流程大致分六步:模型选型与精度确定(决定 FP16 还是量化)→ 引擎选型(vLLM 打底)→ 启动服务并验证 OpenAI 兼容接口 → 压测确定容量(并发、吞吐、P99)→ 设置监控告警 → 上线后按指标持续调优。 压测这一步很多人会跳过,但它决定了容量规划是否靠谱。用 aiohttp 写一个简单压测脚本,模拟真实并发,统计平均延迟和 P99,才能回答"这台机器到底能扛多少 QPS"。```pythonimportasyncio, aiohttp, statistics async def send_prompt(session, prompt): payload={"model":"qwen-7b","messages":[{"role":"user","content":prompt}],"max_tokens":200,"temperature":0.7}start=time.perf_counter()async with session.post("http://localhost:8000/v1/chat/completions",json=payload)as resp: await resp.json()returntime.perf_counter()- start async def benchmark(concurrency=32): prompts=["请详细解释量子计算的基本原理"]* concurrency async with aiohttp.ClientSession()as session: latencies=await asyncio.gather(*[send_prompt(session, p)forpinprompts])returnlatencies``` 注意:压测要用真实的业务 prompt 分布,而不是清一色相同长度。混合长短请求才是线上真实负载,才能测出 Continuous Batching 的真实收益。## 八、GPU 资源调度与多模型部署单机部署只是第一步,规模化部署还要考虑 GPU 资源调度。Kubernetes 上部署推理服务有三大难点:GPU 调度(NVIDIA Device Plugin 分配显存)、共享(多个小模型共享一张卡)、扩缩容(按负载自动增减副本)。实践中常配合自定义调度器,让长任务和短任务错峰,避免把 GPU 显存耗尽导致 OOM。 多模型共存的场景,除了按服务拆分,还可以用 vLLM 的多 LoRA 能力——一个基座模型加载多个业务适配器,按请求动态切换,显存只占一份权重。这对"一个团队多个垂直场景"的部署非常友好。## 九、成本模型:推理成本的三个杠杆推理成本=单价 × 调用量 × 单次 Token 数。三个杠杆对应三条优化路径:模型选型(能用 7B 解决的别上 70B,能路由到小模型的别浪费大模型);缓存与复用(语义缓存、前缀缓存、结果复用);输入控制(精简 Prompt、控制 max_tokens、长文档先摘要再送模型)。我见过不少项目在模型上省了1万元,却在 Prompt 冗余上多花了3万元——成本优化要全链路看,不能只盯着单价。## 十、监控与常见问题关键指标:吞吐(request_success_total)、延迟(e2e_request_latency_seconds)、KV Cache 利用率(gpu_cache_usage_perc)、首 Token 延迟(time_to_first_token_seconds)。常见性能问题按症状定位:P99 高多半是队列堆积,减小 max_num_seqs;吞吐上不去通常是显存不够,量化 + 张量并行;抢占多说明 KV Cache 不够;TTFT 慢是 Prompt 太长,用分块 Prefill。 还有一个经常被忽略的坑:流式响应的稳定性。长连接容易被中间链路掐断,建议用 SSE 协议、加心跳、前端做好重连,否则用户看到的就是"回答到一半断流"。 最后重申三个核心原则:**首选 vLLM**(生态好、性能强、坑少);**量化是必选项**(同样的硬件差4倍吞吐);**监控加调优是持续工作**(上线后根据指标调,而不是一锤定音)。推理优化是系统工程,算法、内存管理、调度、模型压缩四管齐下,才能逼近硬件极限。对团队而言,先把压测和监控体系建起来,再谈优化——没有度量,就没有优化。