Inference Engine Selection
Inference Engine Selection
推理引擎选型不是给工具排总榜,而是把一类工作负载映射到可验证的执行系统。不存在脱离场景的“最好引擎”:同一个引擎可以在离线吞吐测试里占优,却因为 P99、模型格式、硬件拓扑或运维边界而不适合线上服务。
先划清系统边界
选型对象必须处在同一层,否则比较表看起来完整,结论却没有意义。
| 对象 | 主要回答 | 例子 |
|---|---|---|
| 模型容器/量化 recipe | 权重怎样编码和分发 | GGUF、Safetensors、AWQ/GPTQ |
| 推理引擎 | 请求怎样调度,模型怎样执行,KV Cache 怎样管理 | vLLM、SGLang、TensorRT-LLM、llama.cpp |
| 本地模型平台 | 怎样下载、管理并以统一接口运行本地模型 | Ollama |
| Serving platform | 怎样路由、扩缩容、灰度和观测多个引擎副本 | MOC - Serving and LLMOps |
因此“GGUF 和 vLLM 选哪个”是错误问题:前者是数据制品,后者是执行系统;真正的问题是目标模型格式、硬件和引擎 kernel 能否组成有效路径。
从工作负载开始,而不是从功能列表开始
至少先固定以下输入:
- 在线低延迟还是离线吞吐
- 到达率、并发数、输入/输出长度分布和峰谷变化
- TTFT、TPOT、P95/P99、吞吐与成本预算
- 单机/多机拓扑,以及 NVIDIA 专用优化或跨硬件需求
- 长上下文、结构化输出、多 LoRA、前缀复用、PD 分离等能力
- 模型架构、权重/量化格式和对应 kernel 支持
- API、监控、升级、故障恢复与团队维护能力
平均 token/s 不能替代这些约束。短输入长输出主要施压 decode 与 KV 容量;长输入短输出会把 prefill、chunking 和排队策略推到前台;高前缀复用流量又会改变 prefix cache 的收益。
最小决策流程
1 | 记录真实流量形状与 SLO |
硬约束应先于性能 benchmark。例如模型架构或量化 kernel 不受支持,跑分再高也没有候选资格。通过硬约束后,才比较 vLLM、SGLang、TensorRT-LLM、LMDeploy 等同层引擎;llama.cpp 面向本地/边缘路径,Ollama 则多了一层模型管理与 API 封装。
benchmark 必须使用相同模型、数值精度、最大上下文、请求轨迹和采样参数。否则测到的是配置差异,不是引擎差异。结果至少同时保存吞吐、TTFT/TPOT 分位数、GPU/显存利用率、失败率与冷启动/恢复时间。
任何能力矩阵和 CLI 都应记录验证版本与日期;源仓库中的静态框架评价不能作为长期结论。
GGUF 与服务引擎的路由经验
GGUF 主要属于 llama.cpp/Ollama 本地生态;vLLM 的 GGUF 路线目前应视为实验性。典型路由:
| 场景 | 路由 |
|---|---|
| 本地/单机/边缘、CPU 或 Mac、小体积权重 | llama.cpp / Ollama + GGUF |
| HuggingFace Safetensors、NVIDIA GPU、高并发 serving | vLLM / SGLang / TensorRT-LLM |
| Blackwell 原生 FP4/NVFP4 | 先确认引擎和 kernel 支持 |
选型时把“量化文件能不能加载”与“该格式是否有优化 kernel、能否通过任务回归”分开验证。
常见失败方式
- 只看峰值吞吐:长请求占住调度窗口后,短请求 P99 可能恶化。
- 把能加载当成生产可用:fallback kernel、缺失算子或量化反解开销会吞掉理论收益。
- 把引擎当成完整平台:API 可访问不等于已有租户隔离、路由、扩缩容和回滚。
- 用合成固定长度替代真实流量:调度器对长度分布、突发和前缀重复高度敏感。
- 没有保存版本与配置:几周后的升级无法解释性能回归,也无法复现实验。
与其他节点的关系
- 向上:选型 DEPENDS-ON MOC - Serving and LLMOps 给出的 SLO、路由和运维边界。
- 同层:vLLM、SGLang、TensorRT-LLM 与 llama.cpp 是不同工作负载下的平行候选。
- 向下:候选能否成立 DEPENDS-ON Continuous Batching、PagedAttention、并行策略与硬件 kernel。
- 数据制品:GGUF 和 LLM Quantization Deployment 约束可加载路径,但不替代引擎决策。
尚未解决的同层差异见 vLLM 和 SGLang 的调度器区别是什么;在同一请求轨迹上完成实验前,不把功能清单升级成优劣结论。
三类负载的实际候选
对“本地单用户、CPU/Mac、模型频繁切换”的负载,GGUF + llama.cpp/Ollama 的加载与设备覆盖通常比服务端 GPU engine 更重要;应测冷启动、驻留、context 和本地内存,而不是套高并发指标。对“固定 NVIDIA GPU、多租户聊天、输出长度差异大”的负载,vLLM/SGLang/TensorRT-LLM 才进入同层比较,重点是 continuous batching、KV 容量、prefix reuse、P99 和多模型运维。对“结构化程序、共享前缀、约束解码占比高”的负载,SGLang 的状态编排需要单独测 grammar/程序开销;普通聊天跑分不能替代它。
何时应直接淘汰候选
下列情况不是“性能略差”,而是硬淘汰:目标模型/量化格式无法由生产 backend 正确执行;需要的 TP/PP/多节点拓扑没有可验证路径;缺失结构化输出、流式取消或多 LoRA 等业务契约;冷启动/升级/回滚时间超过 SLO;或者只能靠 undocumented fallback kernel 才能启动。候选进入 benchmark 前先做这些门槛检查,可以避免用一场漂亮的吞吐测试掩盖上线不可行性。
把服务平台成本算进去
引擎 benchmark 之外还要估算镜像/权重体积、启动时间、GPU 节点亲和、metrics/trace、滚动升级、模型版本回滚和故障时正在生成的请求如何处理。一个 engine 单机快 10%,如果无法满足路由、灰度和恢复,平台层的额外复杂度会轻易吞掉收益。最终选型产物应包括 workload fingerprint、硬约束淘汰表、benchmark 原始数据和保留/回滚理由,而不是只有一张功能矩阵。