漫话大模型:同一个模型,换台机器效果就不同?——推理引擎这个隐形选手

你有没有遇到过这种情况:

同一份模型权重,部署到 A 机器上跑得好好的,换到 B 机器上,回答质量明显下降------逻辑变差、输出乱码、甚至直接崩溃。

模型一样、参数一样、prompt 一样,效果就是不一样。

老七自己工作中就踩过这个坑。排查了好几天,最后发现:不是模型的问题,不是机器的问题------是推理引擎不一样。

A 机器用的是 vLLM,B 机器用的是另一套。同一个模型,换个引擎,效果就变了。

这篇就讲清楚:推理引擎是什么,为什么它能让同一个模型跑出不同效果,以及怎么选。


一、推理引擎是什么

打个比方:模型权重是菜谱,推理引擎是厨房。

同一份菜谱(模型权重),交给不同的厨房(推理引擎),做出来的菜可能味道不同------因为每个厨房的灶台火力、锅的材质、厨师手法都不一样。

具体来说,推理引擎干三件事:

① 把模型权重加载进 GPU------把几百 GB 的权重文件读进显存,这步看着简单,但不同引擎的加载方式、精度处理(FP16/BF16/INT8/FP4)不同,加载完的模型可能已经有细微差异了

② 接收请求,跑前向计算------用户发一个 prompt 进来,引擎要算 attention、跑 FFN、生成 token。每一步的算子实现(矩阵乘法、RoPE 位置编码、softmax)都可能跟另一个引擎的实现不完全一样

③ 管理资源------KV Cache 怎么存、多个请求怎么并行、显存怎么分配。这些不影响"算什么",但影响"算多快"

前两件事决定了效果差异,第三件事决定了性能差异。


二、为什么同一个模型会跑出不同效果

即使你关掉了所有随机性设置(temperature=0、top_p=1),同一个模型在不同引擎上的输出仍然可能不同。

这有两类原因------一类是引擎的 bug(可以修),一类是浮点运算的固有性质(无法消除)。

原因一:引擎的 bug(可以修)

2025 年,一篇 arXiv 论文(2506.09713)系统性地分析了五大推理引擎的 929 个 bug。论文专门定义了一类叫"不一致输出"的 bug------占所有意外输出的 17%。典型的有四种:

① 算子实现错误

最常见。比如 RoPE(旋转位置编码)------Transformer 里给 token 加位置信息的算子。vLLM 有一个 bug(issue #590),RoPE 实现有误,导致模型"看错"了 token 的位置,输出自然就乱了。

② 精度不匹配

TensorRT-LLM 有一个 bug(issue #1303),用 INT8 精度转换模型但引擎跑的是 BF16,精度对不上,计算结果就偏了。

③ 后端不兼容

引擎要为不同的 GPU 后端(CUDA、Vulkan、Metal)手写算子。同一个矩阵乘法,CUDA 版和 Metal 版的实现可能不完全等价。

④ 分词器错误

最隐蔽。Llama.cpp 有一个 bug(issue #290),分词器直接把"china"这个 token 丢了------模型根本没看到这个词,当然答不对。

原因二:浮点运算的固有性质(无法消除)

就算引擎没有 bug、精度也完全一致,不同引擎仍然可能输出不同。这不是工程问题,是数学问题

浮点加法不满足结合律。 比如 FP16 下:

ini 复制代码
(1 + 0.001) + 0.001 = 1.001    ← 0.001 太小被吸收了
1 + (0.001 + 0.001) = 1.002    ← 先加再合,没被吸收

同一个矩阵乘法,vLLM 的 CUDA kernel 和 TensorRT-LLM 的 fused kernel,计算顺序不同------谁先加谁后加不一样,结果就有微小差异。

这个差异在第一步可能只有 1e-7,但生成 1000 个 token 时,每一步都依赖前面所有步的 KV Cache。误差在第 500 步可能放大到 1e-3------已经足以改变 softmax 的选择,选了不同的 token,然后整个后续序列分叉。

短序列基本一致,长序列可能分叉。 这不是谁写错了,是浮点数在计算机里的数学性质。

小结

两类原因,性质完全不同:

原因 能不能消除 影响程度
引擎 bug 算子写错、精度不匹配、分词器丢 token 能(修 bug) 可能严重(乱码、答非所问)
浮点固有差异 计算顺序不同 + 长序列误差累积 不能(数学性质) 通常轻微(偶尔换一个 token)

一句话总结:推理引擎不是"忠实执行模型"的透明管道------它有自己的 bug(可以修),也有浮点运算的固有代价(无法消除)。序列越长,代价越大。


三、四大引擎横评

2026 年主流的推理引擎就四个,各自的核心杀手锏不同:

vLLM ------ 通用之王

杀手锏:PagedAttention------把 KV Cache 像 OS 管虚拟内存一样分页管理,消除显存碎片,大幅提升并发能力。

特点:开箱即用、对新模型支持最快(开源模型发布当天 vLLM 基本就能跑)、跨 GPU 类型(NVIDIA/AMD 都行)。

适合:快速上线、频繁换模型、小团队没 MLOps。

TensorRT-LLM ------ 性能怪兽

杀手锏:编译器式优化------把模型针对特定 GPU 架构编译成专用引擎,内核融合 + FP8 量化,吞吐量拉满。

特点:最快,但最重。编译一个 70B 模型要几十分钟,编译产物绑定 GPU 架构(H100 编译的不能跑 A100)。只支持 NVIDIA。

适合:稳定高流量、固定 GPU、有工程团队维护编译流程。

SGLang ------ 前缀复用专家

杀手锏:RadixAttention------把共享的 prompt 前缀(比如 system prompt)存进 radix 树,多个请求复用同一份 KV Cache。前缀只算一次,后续请求直接复用。

特点:在"多轮对话""固定 system prompt""RAG 批处理"这类共享前缀场景下比 vLLM 快 29%。但独特 prompt 场景下优势消失。

适合:多轮对话、固定模板、RAG 场景。

TGI(Text Generation Inference)------ Hugging Face 全家桶

杀手锏:跟 Hugging Face 生态深度绑定,模型下载、权重转换、量化一键搞定。

特点:部署最简单,但性能不是最优。适合原型验证和轻量部署。

适合:快速验证、Hugging Face 生态用户。

一张选型表

你的场景 推荐 理由
快速上线、频繁换模型 vLLM 开箱即用、新模型支持最快
稳定高流量、固定 GPU TensorRT-LLM 吞吐量最高、FP8 加持
多轮对话、固定 system prompt SGLang 前缀复用省算力
快速验证、轻量部署 TGI HF 生态一键部署

四、推理性能:不只是"快不快"

除了效果差异,推理引擎的性能差异也很大。不只是"谁吞吐高",还有几个维度:

跨机器并行(Tensor Parallelism)

70B 模型一张 GPU 装不下,要拆到多张卡上跑。怎么拆?

  • 列并行:把权重矩阵按列切,每张卡算一部分,最后拼结果
  • 行并行:把权重矩阵按行切,每张卡算一部分,最后加起来

不同引擎的切分策略和通信效率不同------同样的 4 卡并行,vLLM 可能比 TGI 快 30%,因为通信开销更小。

KV Cache 管理

生成 1000 个 token 时,前面 999 个 token 的 KV Cache 都得存着。vLLM 的 PagedAttention 把这些 Cache 分页存储(像虚拟内存),不浪费一个字节;传统做法是预分配一块大显存,用不满就浪费。

Continuous Batching(连续批处理)

传统做法:等一个 batch 的所有请求都生成完,才接新请求。如果有一个请求要生成 2000 个 token,其他只生成 50 个的请求也得等它。

Continuous Batching:请求来一个塞一个,走一个腾一个------像流水线,不等齐。vLLM、SGLang、TGI 都支持,TensorRT-LLM 也支持但配置更复杂。


五、怎么避免"换引擎效果变差"

几个实操建议:

① 跑基准对比

部署前,用同一组测试 prompt 在不同引擎上跑一遍,对比输出。重点关注:长文本生成(累积误差最明显)、多语言混合(分词器差异最容易暴露)、数学推理(精度敏感)。

② 固定精度

明确指定精度(FP16 或 BF16),不要让引擎自动选。不同引擎的默认精度可能不同------vLLM 默认 FP16,TensorRT-LLM 可能默认 INT8。

③ 关掉所有随机性

对比效果时 temperature 设 0、top_p 设 1、top_k 设 -1。如果这样还有差异,那就是引擎本身的算子实现差异------要么接受,要么换引擎。

④ 选引擎时先看生态支持

不是所有引擎都支持所有模型。新开源模型发布后,vLLM 通常当天就支持;TensorRT-LLM 可能要等几周。先确认你要用的模型在目标引擎上有官方支持,别自己魔改。


写在最后

如果这篇只记住一件事:

模型权重决定能力上限,推理引擎决定实际下限。同一个模型换个引擎,效果和性能都可能天差地别------这不是 bug,是推理引擎作为"翻译层"的固有代价。

选引擎不是"选最快的",是"选最适合你的场景的"。快速验证用 vLLM,高流量生产用 TensorRT-LLM,多轮对话用 SGLang------没有银弹,只有匹配。


参考资料


本文首发于公众号「程序员于老七」《漫话大模型》系列,欢迎关注。

相关推荐
liulilittle4 小时前
为什么需要回程闲置保护?
ai·llm·prompt·agent·tools·subagent·opencode
七牛开发者4 小时前
HarnessDev:让 LLM 自己创建并迭代 Agent Harness
chatgpt·llm·agent
桃西西呀5 小时前
红酒标签上的 87 分是怎么算出来的?我拿 1599 瓶真酒把线性回归和逻辑回归拆开讲
人工智能·机器学习·llm
uncle_ll8 小时前
从 localStorage 到 Chrome 商店:一个 HTML 文件的 7 次重构
llm·agent·codex·workbuddy
武子康8 小时前
9/10 和 900/1000 都是 90%:机器人成功率计算器必须阻止的误判
人工智能·llm·agent
武子康9 小时前
第一次用 SGLang:把本地模型接进聊天应用
人工智能·llm·agent
Web极客码11 小时前
Pydantic 校验通过不等于答案正确:如何识别 LLM 的语义错误
服务器·人工智能·ai·llm
流浪00111 小时前
大模型技术全景(六):AI 的“逐字接龙“——Token 与自回归生成背后的真相
开发语言·人工智能·llm
米小虾1 天前
告别逐 token 蹦字:扩散语言模型(dLLM)到底能不能终结自回归?
人工智能·llm