模型推理的推理引擎切换:vLLM、TGI 与 TensorRT-LLM 对比
模型推理的推理引擎切换vLLM、TGI 与 TensorRT-LLM 对比选推理引擎不是选最快的那个而是选最契合你业务模式的那个。一、场景痛点你的团队选了一个开源 LLM 做在线推理服务第一版用 HuggingFace Transformers 直接跑——延迟 2 秒用户直接关页面。然后你开始做优化发现可选方案有 vLLM、TGIText Generation Inference、TensorRT-LLM每个都说自己是最快。你读了三个项目的 README、跑了十几个 benchmark、看了几十篇技术博客最后发现最难的并不是技术选型而是搞清楚你的业务到底是吞吐优先还是延迟优先、是单一模型还是多模型共存、是一次性部署还是需要频繁更新。没有银弹。每个引擎都是为特定场景设计的选错的代价不是性能差 20%而是整个推理架构需要推倒重来。二、底层机制与原理剖析2.1 三大引擎的核心差异2.2 PagedAttentionvLLM 的杀手特性KV Cache 是推理时最占内存的东西。传统实现中每个请求的 KV Cache 是连续分配的一块显存——这意味着你需要预留max_seq_len × num_layers × 2 × hidden_dim的内存哪怕实际请求只有 50 个 token。PagedAttention 把 KV Cache 切成固定大小的页类似操作系统中的内存分页按需分配不需要预留整块内存。这带来了两个巨大收益显存利用率从 30% 提升到 90%——同样的 GPU 可以服务 3 倍的并发请求Prefix Sharing多个请求有共同前缀如 system prompt共享同一块 KV Cache 页传统 KV Cache: [####################################___________] 浪费 40% PagedAttention: [####][####][####][____] 按需分配 ↑ 未使用的块可以给其他请求2.3 In-flight Batching vs Continuous Batching特性Continuous Batching (vLLM)In-flight Batching (TRT-LLM)合并时机每次 forward 调用前检查和重组推理进行中动态插入/移除请求实现方式Python 层调度调用 GPU kernelC 运行时 CUDA graph对新请求的响应下一个 iteration 加入当前 iteration 就能插入适合场景批量离线推理实时在线推理三、生产级代码实现3.1 推理引擎抽象层 推理引擎抽象层统一 vLLM、TGI、TensorRT-LLM 的调用接口 支持运行时引擎切换让业务代码不绑定具体引擎 设计原则: 1. 引擎选择通过环境变量或配置不硬编码 2. 统一的 generate / generate_stream 接口 3. 引擎特定的参数通过 extra_params 透传 from abc import ABC, abstractmethod from typing import AsyncIterator, Optional from dataclasses import dataclass from enum import Enum import os class InferenceEngineType(Enum): 推理引擎类型枚举 VLLM vllm TGI tgi TENSORRT_LLM tensorrt_llm HUGGINGFACE huggingface dataclass class GenerationConfig: 生成配置与引擎无关 max_tokens: int 2048 temperature: float 0.7 top_p: float 0.95 top_k: int 50 repetition_penalty: float 1.1 stop_sequences: Optional[list[str]] None # 引擎特有参数透传 extra_params: Optional[dict] None dataclass class GenerationResult: 生成结果 text: str input_tokens: int output_tokens: int finish_reason: str # stop / length / error latency_ms: float # 首 token 延迟 total_latency_ms: float # 总延迟 tokens_per_second: float # 吞吐 class InferenceEngine(ABC): 推理引擎抽象基类 所有引擎实现必须实现 generate 和 generate_stream 两个方法 abstractmethod async def generate(self, prompt: str, config: GenerationConfig) - GenerationResult: 同步生成等待完整结果 pass abstractmethod async def generate_stream( self, prompt: str, config: GenerationConfig ) - AsyncIterator[str]: 流式生成逐 token 输出 pass abstractmethod async def health_check(self) - bool: 健康检查 pass abstractmethod async def get_metrics(self) - dict: 获取引擎指标 pass # vLLM 引擎实现 class VLLMEngine(InferenceEngine): vLLM 引擎封装 使用 OpenAI 兼容 API 调用 优势: PagedAttention 高吞吐、_prefix caching、continuous batching 劣势: Python 运行时开销、冷启动慢 def __init__(self, base_url: str, model_name: str): self.base_url base_url.rstrip(/) self.model_name model_name self.client None # openai.AsyncOpenAI 实例 async def generate(self, prompt: str, config: GenerationConfig) - GenerationResult: import time start time.perf_counter() # vLLM 的 OpenAI 兼容 API response await self.client.completions.create( modelself.model_name, promptprompt, max_tokensconfig.max_tokens, temperatureconfig.temperature, top_pconfig.top_p, extra_body{ top_k: config.top_k, repetition_penalty: config.repetition_penalty, stop: config.stop_sequences, **(config.extra_params or {}) } ) elapsed time.perf_counter() - start choice response.choices[0] return GenerationResult( textchoice.text, input_tokensresponse.usage.prompt_tokens, output_tokensresponse.usage.completion_tokens, finish_reasonchoice.finish_reason or stop, latency_mselapsed * 1000, # vLLM 暂不区分首 token total_latency_mselapsed * 1000, tokens_per_secondresponse.usage.completion_tokens / elapsed ) async def generate_stream( self, prompt: str, config: GenerationConfig ) - AsyncIterator[str]: stream await self.client.completions.create( modelself.model_name, promptprompt, max_tokensconfig.max_tokens, temperatureconfig.temperature, top_pconfig.top_p, streamTrue, extra_body{ top_k: config.top_k, repetition_penalty: config.repetition_penalty, stop: config.stop_sequences, **(config.extra_params or {}) } ) async for chunk in stream: if chunk.choices and chunk.choices[0].text: yield chunk.choices[0].text async def health_check(self) - bool: try: resp await self.client.models.list() return True except Exception: return False async def get_metrics(self) - dict: vLLM 指标通过 /metrics 端点暴露 import aiohttp async with aiohttp.ClientSession() as session: async with session.get(f{self.base_url}/metrics) as resp: raw_metrics await resp.text() # 解析 Prometheus 格式指标 return {raw: raw_metrics} # TensorRT-LLM 引擎实现 class TensorRTLLMEngine(InferenceEngine): TensorRT-LLM 引擎封装 通过 Triton Inference Server 的 gRPC 接口调用 优势: GPU kernel 级优化、FP8/INT4 硬件加速、C 运行时低延迟 劣势: 模型转换复杂、不支持所有模型架构、更新慢 def __init__(self, triton_url: str, model_name: str): self.triton_url triton_url self.model_name model_name # 使用 tritonclient.grpc 或 HTTP async def generate(self, prompt: str, config: GenerationConfig) - GenerationResult: import time start time.perf_counter() # TensorRT-LLM 通过 Triton 暴露协议为 gRPC 或 HTTP # 这里使用简化的 HTTP 调用示意 import aiohttp payload { text_input: prompt, max_tokens: config.max_tokens, temperature: config.temperature, top_p: config.top_p, top_k: config.top_k, stop_words: config.stop_sequences or [], bad_words: [], stream: False } async with aiohttp.ClientSession() as session: async with session.post( f{self.triton_url}/v2/models/{self.model_name}/generate, jsonpayload ) as resp: data await resp.json() elapsed time.perf_counter() - start return GenerationResult( textdata.get(text_output, ), input_tokensdata.get(input_tokens, 0), output_tokensdata.get(output_tokens, 0), finish_reasonstop, latency_mselapsed * 1000, total_latency_mselapsed * 1000, tokens_per_seconddata.get(output_tokens, 0) / elapsed ) async def generate_stream( self, prompt: str, config: GenerationConfig ) - AsyncIterator[str]: import aiohttp payload { text_input: prompt, max_tokens: config.max_tokens, temperature: config.temperature, top_p: config.top_p, top_k: config.top_k, stop_words: config.stop_sequences or [], stream: True } async with aiohttp.ClientSession() as session: async with session.post( f{self.triton_url}/v2/models/{self.model_name}/generate_stream, jsonpayload ) as resp: async for line in resp.content: if line: text line.decode(utf-8).strip() if text.startswith(data: ): yield text[6:] async def health_check(self) - bool: import aiohttp try: async with aiohttp.ClientSession() as session: async with session.get(f{self.triton_url}/v2/health/ready) as resp: return resp.status 200 except Exception: return False async def get_metrics(self) - dict: import aiohttp async with aiohttp.ClientSession() as session: async with session.get(f{self.triton_url}/v2/models/{self.model_name}/stats) as resp: return await resp.json() # 引擎工厂 class InferenceEngineFactory: 推理引擎工厂根据配置创建对应的引擎实例 使用方式: engine InferenceEngineFactory.create() result await engine.generate(Hello, GenerationConfig()) _registry { InferenceEngineType.VLLM: VLLMEngine, InferenceEngineType.TENSORRT_LLM: TensorRTLLMEngine, } classmethod def create(cls, engine_type: Optional[InferenceEngineType] None) - InferenceEngine: 创建推理引擎实例 优先级: 参数指定 环境变量 默认 vLLM if engine_type is None: engine_type InferenceEngineType( os.getenv(INFERENCE_ENGINE, vllm) ) engine_cls cls._registry.get(engine_type) if engine_cls is None: raise ValueError(f不支持的引擎类型: {engine_type}) # 从环境变量读取引擎连接信息 base_url os.getenv( f{engine_type.value.upper()}_URL, http://localhost:8000 ) model_name os.getenv(MODEL_NAME, default) return engine_cls(base_url, model_name) # 使用示例 async def main(): engine InferenceEngineFactory.create(InferenceEngineType.VLLM) # 流式生成 config GenerationConfig(max_tokens512, temperature0.7) async for token in engine.generate_stream(解释量子纠缠, config): print(token, end, flushTrue)3.2 引擎切换的决策逻辑 推理引擎选择策略根据请求特征自动路由到最合适的引擎 路由规则: - 实时对话 (streaming, 100 tokens/s) → TensorRT-LLM (低延迟) - 批量生成 (batch, 1000 tokens) → vLLM (高吞吐) - 离线批处理 → vLLM (PagedAttention 高并发) - 非主流模型架构 → vLLM (兼容性好) from dataclasses import dataclass from enum import Enum class RequestType(Enum): CHAT chat # 实时对话流式 BATCH batch # 批量生成 OFFLINE offline # 离线批处理 dataclass class RoutingRequest: prompt: str request_type: RequestType max_tokens: int stream: bool False def route_engine(request: RoutingRequest) - InferenceEngineType: 根据请求特征选择推理引擎 # 规则 1: 实时对话 → TensorRT-LLM低延迟in-flight batching if request.request_type RequestType.CHAT and request.stream: return InferenceEngineType.TENSORRT_LLM # 规则 2: 大批量生成 → vLLMPagedAttention 高并发 prefix caching if request.request_type in (RequestType.BATCH, RequestType.OFFLINE): return InferenceEngineType.VLLM # 默认: vLLM兼容性最好 return InferenceEngineType.VLLM async def execute_with_engine(request: RoutingRequest) - str: 自动路由到最合适的引擎执行推理 engine_type route_engine(request) engine InferenceEngineFactory.create(engine_type) config GenerationConfig(max_tokensrequest.max_tokens) if request.stream: result_parts [] async for token in engine.generate_stream(request.prompt, config): result_parts.append(token) return .join(result_parts) else: result await engine.generate(request.prompt, config) return result.text四、边界分析与架构权衡4.1 性能不是唯一维度维度vLLMTGITensorRT-LLM单请求延迟中中低并发吞吐高中中模型兼容性高支持 50 架构高低需 TRT 引擎量化支持GPTQ/AWQ/SqueezeLLMGPTQ/AWQ/BitsAndBytesFP8/INT4 (硬件加速)部署复杂度低 (pip install)低 (docker)高 (模型转换 Triton)更新频率极高周更中月更低季更社区生态Python 生态完整HuggingFace 官方NVIDIA 企业支持场景建议快速验证阶段→ vLLM。pip install 起一个服务5 分钟跑通生产在线服务→ TensorRT-LLM。花一周做模型转换和 kernel 调优换取 2-3 倍的推理性能大量模型混用→ vLLM。你不可能把 50 个模型都转成 TRT 引擎HuggingFace 重度用户→ TGI。和 HF Hub 的集成最紧密4.2 引擎迁移的隐性成本从 vLLM 切到 TensorRT-LLM 不只是改几行代码模型转换时间70B 模型转 TRT 引擎大约需要 2-4 小时A100TRT 引擎文件体积通常是原始权重的 1.5-2 倍因为包含了优化后的 kernel不支持的算子某些自定义 attention 或 activation 函数需要手写 TRT plugin运维复杂度Triton Server 的配置比 vLLM 的 OpenAI API 复杂一个数量级4.3 混合部署策略我们最终采用了双引擎并存的架构TensorRT-LLM 跑流量最大的核心模型3 个模型部署在 8×A100 节点上vLLM 跑长尾模型和实验模型20 个部署在 4×A100 节点上前端统一网关根据model_name路由到不同引擎这样既享受了 TRT 的性能优势又保留了 vLLM 的灵活性和生态兼容性。五、总结选推理引擎的三个原则先看业务需求再看 benchmark。延迟敏感型选 TRT-LLM吞吐敏感型选 vLLM和 HuggingFace 生态深度绑定选 TGI。不要追求一个引擎统治所有场景。双引擎甚至三引擎并存是合理的通过统一抽象层屏蔽差异。考虑全生命周期成本不只是推理延迟。TRT-LLM 的 2ms 延迟优势可能被几小时的模型转换时间、运维复杂度、和有限的模型兼容性所抵消。最后这三个引擎的竞争正在让整个生态快速进化——vLLM 在抄 TRT 的 in-flight batchingTRT 在兼容更多模型TGI 在优化吞吐。一年后的格局可能完全不同。所以把引擎选择做成可替换的比选对更重要。

相关新闻

如何完全免费解锁Wand Pro高级功能:本地增强器终极指南

如何完全免费解锁Wand Pro高级功能:本地增强器终极指南

如何完全免费解锁Wand Pro高级功能:本地增强器终极指南 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer Wand-Enhancer是一款完全开源、…

2026/10/19 17:25:09 阅读更多 →
3步快速搞定!国家中小学智慧教育平台电子教材一键下载完整指南

3步快速搞定!国家中小学智慧教育平台电子教材一键下载完整指南

3步快速搞定!国家中小学智慧教育平台电子教材一键下载完整指南 【免费下载链接】tchMaterial-parser 国家中小学智慧教育平台 电子课本下载工具,帮助您从智慧教育平台中获取电子课本的 PDF 文件网址并进行下载,让您更方便地获取课本内容。 …

2026/10/18 7:01:55 阅读更多 →
SRIO高速串行互连技术实战:从初始化到错误恢复的嵌入式系统通信指南

SRIO高速串行互连技术实战:从初始化到错误恢复的嵌入式系统通信指南

1. 项目概述与SRIO技术价值在嵌入式系统,尤其是雷达信号处理、无线基站基带或者高端医疗影像设备里,芯片之间怎么“说话”是个核心问题。你想想,几个DSP或者FPGA要协同处理海量的数据流,如果通信带宽不够、延迟太高,整…

2026/10/18 7:01:58 阅读更多 →

最新新闻

Pallas引擎如何看穿AI写作?从降AI到人机协同的正确路径

Pallas引擎如何看穿AI写作?从降AI到人机协同的正确路径

先说结论:2026年了,还在问“怎么降AI”的人,思路本身就反了。真正的答案不是研究怎么骗过Pallas引擎,而是研究为什么它盯上你。我把国内外主流AIGC检测工具,包括知网近期升级的Pallas引擎思路做了拆解,结合…

2026/10/20 7:14:56 阅读更多 →
Boost PFC CCM平均电流控制与相位补偿的Plecs仿真实战

Boost PFC CCM平均电流控制与相位补偿的Plecs仿真实战

做开关电源仿真绕不开PFC这个话题。最近我把Boost PFC的CCM平均电流控制叠加电流相位补偿控制,在Plecs里完整跑了一遍仿真,从主电路参数计算到控制环路搭建,再到波形分析和问题排查,整个过程踩了几个坑,也把原理重新梳…

2026/10/20 7:14:56 阅读更多 →
批量出图怎样做到像素级可控?规则渲染管线实战解析

批量出图怎样做到像素级可控?规则渲染管线实战解析

这个需求最近真的很多人问。我自己的项目里也是碰到一模一样的瓶颈:业务方要求批量出图,图片里不能有丝毫随机性——同样的输入必须产出同样的构图、同样的配色、同样的文字位置。拿通用多模态生成模型试了几轮,效果确实惊艳,但根…

2026/10/20 7:14:56 阅读更多 →
litellm:统一大模型接入层,解决多模型切换与适配之痛

litellm:统一大模型接入层,解决多模型切换与适配之痛

最近在做一个多模型调度的内部项目时,我把团队的模型接入层整体切换到了 litellm。这个决定帮我省掉了大量重复的适配代码,也让我们在评估不同大模型服务时效率高了不少。如果你同样被"每个模型一套 SDK、一套请求格式、一套报错风格"折磨过&a…

2026/10/20 7:14:56 阅读更多 →
新手考古路线图:3 步定位登月舱降落代码 BURN, BABY, BURN——从 Luminary099 源码索引到 P63 着陆算法

新手考古路线图:3 步定位登月舱降落代码 BURN, BABY, BURN——从 Luminary099 源码索引到 P63 着陆算法

新手考古路线图:3 步定位登月舱降落代码 BURN, BABY, BURN——从 Luminary099 源码索引到 P63 着陆算法 【免费下载链接】Apollo-11 Original Apollo 11 Guidance Computer (AGC) source code for the command and lunar modules. 项目地址: https://gitcode.com/…

2026/10/20 7:14:56 阅读更多 →
投机推理:突破大模型自回归瓶颈的并行验证加速技术

投机推理:突破大模型自回归瓶颈的并行验证加速技术

1. 大模型推理的“车堵一条道”困局老做推理优化的朋友都有过这种体验:GPU 明明算力爆炸强,但每次生成一个 token 都得几毫秒甚至几十毫秒,batch 稍微大一点,延时就像坐火箭一样往上蹿。一开始我们都骂“模型太大了”,…

2026/10/20 7:13:55 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/19 10:02:04 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 9:10:22 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →