LLM 推理引擎与本地 AI 硬件(2026 版)

你不是先挑推理引擎。你先定下硬件策略、workload 形态和 serving 模式,引擎是跟着这些走的。

这是思考 LLM 推理引擎最有用的方式。

系列说明: 这是我「自托管 LLM / 本地 AI」教学系列的第 3 篇。

那两篇讲的是硬件的容量和带宽数学。

这一篇讲的是把硬件变成可用推理能力的那一层软件。

Engines(引擎)

这些工具用途各异,处在不同的层:

  • 本地可移植性
  • 消费级 CUDA
  • Apple 统一内存(unified memory)工作流
  • 量化推理
  • 生产级 serving
  • 分布式编排
  • 厂商优化的数据中心执行

一个有用的心智模型:

推理引擎不是「模型」本身。它是交通警察、内存管理器、kernel 分发器、调度器、缓存记账员、并行规划器、API 入口,有时还是部署框架。

最好的引擎,要匹配你的内存层级(memory hierarchy)互联(interconnect)量化格式延迟和吞吐目标模型架构,以及运维成熟度

一页纸决策指南

  • 笔记本 / 边缘 / 古怪硬件 → llama.cpp
  • Mac 优先工作流 → MLX / MLX-LM
  • 单张 RTX 本地推理 → ExLlamaV2
  • 2-4+ 张 NVIDIA / CUDA GPU → ExLlamaV3
  • 通用生产级 serving → vLLM
  • 长上下文 / MoE / 路由 → SGLang
  • NVIDIA 极致性能 → TensorRT-LLM
  • 集群编排 → NVIDIA Dynamo

本指南剩下的部分讲的是为什么。

推理引擎到底干了什么

推理引擎要加载权重、对输入分词、跑前向传播、采样 token、维护 KV cache,并把结果流式输出。正经的引擎还要处理批处理(batching)、调度、前缀缓存(prefix caching)、量化、并行执行、API serving、指标,以及分布式执行。

这套 workload 有两个阶段:

Prefill(预填充) 读入 prompt、建起初始的 KV cache。它是计算密集型的。

Decode(解码) 一次生成一个 token,反复读取权重和 KV cache。它受内存带宽制约。decode 速度更多取决于内存带宽,而不是峰值算力。

这个区分几乎能解释一切:

  • 短 prompt、长回答: decode 主导 → 内存带宽和批处理很关键。
  • 长 prompt、短回答: prefill 主导 → attention kernel 和分块预填充(chunked prefill)很关键。
  • 多用户: 调度器质量很关键 → 连续批处理、缓存分页、公平性。
  • 长上下文: KV cache 主导 → paged attention、KV 量化、offload。
  • MoE: 专家路由主导 → 专家并行(expert parallelism)、互联、grouped GEMM。
  • 多节点: 互联主导 → NVLink、RDMA、流水线并行(pipeline parallelism)、分离(disaggregation)。

PagedAttention 解决了 KV cache 的碎片化。FlashAttention 用 IO 感知的分块(tiling)削减了 HBM(高带宽内存)的流量。推测解码(speculative decoding)先草拟出廉价的 token,再并行去验证它们。反复出现的主题是:推理性能 = 内存搬运 + 调度。

真正的瓶颈

1. 是内存带宽,不只是 VRAM 大小。 VRAM 决定能不能装下。带宽决定 decode 多快。Apple 的 M3 Ultra 提供最高 819 GB/s 的统一内存带宽。NVIDIA 的 H100 SXM 标称 3.35 TB/s 的 GPU 内存带宽。统一内存让你能装下那些塞不进消费级 VRAM 的模型。而当模型装得下时,HBM 让你得更快。装得下不等于跑得快。容量不等于带宽。

2. KV cache 的增长。 KV cache 随 batch size 和上下文长度增长。长上下文 workload 哪怕权重装得下,也可能耗尽内存。PagedAttention 把 KV cache 切成块(block),提高利用率、支撑更大的 batch。

3. 互联。 模型一旦跨过 GPU 边界(多 GPU),你就得付通信代价。张量并行(tensor parallelism)需要频繁的 all-reduce 集合通信。流水线并行在阶段边界处通信。专家并行为 MoE 需要 all-to-all 流量。vLLM 的文档指出,没有 NVLink 时,流水线并行可能跑得比张量并行还快。

4. 调度器质量。 一个好的调度器要决定哪些请求进入 batch、prefill 和 decode 如何共享加速器、长 prompt 会不会卡住短 decode,以及如何避免饿死(starvation)。「支持批处理」和「表现得像个生产级调度器」不是一回事。

5. 运行时开销。 CUDA graph、kernel 融合、采样开销、tokenizer 开销、HTTP 开销、LoRA 切换、结构化解码,全都有影响。在大规模下,那些烦人的 2% 开销会拧成一股合力,集体讨要你的 attention(无意双关)。

引擎家族

大致分四个家族:

可移植本地运行时(Portable local runtimes): llama.cpp、MLC LLM、ONNX Runtime GenAI、OpenVINO、Ollama 式工具。它们关心的是「让它能在这里跑起来」。

Apple / 统一内存运行时: MLX 和 MLX-LM。它们关心的是「用好大块共享内存和 Apple 的技术栈」。

消费级 CUDA 量化引擎: ExLlamaV2 和 ExLlamaV3。它们关心的是「用低 bit 权重让我的 3090/4090/5090 机器嗷嗷叫」。

生产级 serving 引擎: vLLM、SGLang、TensorRT-LLM、TGI、LMDeploy。它们关心的是并发用户、KV cache、批处理、并行、可观测性,以及每 token 成本。

再往上还有 编排层(orchestration layers),比如 Dynamo,它坐在引擎之上,协调机群、分离式 prefill/decode、路由和自动扩缩。

llama.cpp:可移植性之王

当硬件古怪、受限、离线、偏 CPU、面向边缘,或者根本不是一台规整的 NVIDIA 数据中心节点时,答案就是 llama.cpp。

它支持 Apple Silicon(经由 ARM NEON、Accelerate、Metal);x86(经由 AVX/AVX2/AVX512/AMX);RISC-V;低 bit 量化;CUDA;AMD(经由 HIP);MUSA;Vulkan;SYCL;以及 CPU+GPU 混合 offload。这就是为什么 llama.cpp 牢牢占住「先让它跑起来」这条赛道。

它的 HTTP 服务器比一个「玩具级本地运行器」能干得多。llama-server 提供 OpenAI 兼容路由、Anthropic Messages API 兼容、重排序(reranking)、连续批处理、多模态支持、JSON schema 约束、函数调用、推测解码,还有一个 web UI。

关键局限:llama.cpp 不适合正经的多节点生产级 serving。它的 RPC 后端在文档里被明确标注为概念验证(proof-of-concept)、脆弱且不安全。

结论: 当可移植性、离线运行、GGUF 或混合 offload 比机群规模的 serving 更重要时,用 llama.cpp。

不要在 多 GPU 上用它。

MLX 和 MLX-LM:Apple Silicon 上的利器

MLX 是 Apple 为 Apple Silicon 打造的数组框架,MLX-LM 是建在它之上的 LLM 包。这是一套 Mac 优先的 ML 技术栈。

关键的硬件事实是统一内存。Apple Silicon 让 CPU 和 GPU 直接访问同一个内存池。MLX 的数组就活在统一内存里,你是在执行运算时选择设备,而不是在分离的内存空间之间搬运数组。

这改变了本地推理的取舍。在独立 GPU 系统上,问题是「它装得进 VRAM 吗?」在一台拥有大块统一内存的 M 系列 Mac 上,问题变成了「它装得进内存吗,而且内存系统能不能足够快地喂饱 GPU?」大块的量化模型,能装进那些在 24 GB 消费级 GPU 上根本不可能跑的机器里。

但是,它也更慢

MLX-LM 加上了 Hugging Face Hub 集成、量化、LoRA 和全量微调、分布式推理,以及一个庞大的 MLX Community 模型生态。MLX 也不再只限 Mac:它为 Linux 提供 CUDA 和纯 CPU 的包。分布式通信支持 MPI、基于 TCP 的 Ring、用于 Thunderbolt RDMA 的 JACCL,以及用于 CUDA 的 NCCL。

MLX-LM 的服务器自己就警告说,不建议用于生产,因为它只实现了基础的安全检查。

结论: Mac 优先的 ML 和 LLM 工作流用 MLX。要做高并发的公开 serving,从一套真正的 serving 栈起步。

ExLlamaV2 和 V3:消费级 CUDA,调校到位、够快

ExLlamaV2 是给那些想让一张消费级 NVIDIA GPU 以小博大的人用的本地 CUDA 量化引擎。它支持 paged attention、动态批处理、prompt 缓存、KV cache 去重、批量生成、流式输出和推测解码。要记住的词是本地(local)。它让量化模型在现代 CUDA GPU 上跑得快,尤其是消费级卡。

最佳场景:一台单 RTX 3090/4090/5090 机器、本地编码助手、本地聊天、EXL2 量化模型,以及高端发烧友(prosumer)工作站用途。

ExLlamaV3 把这套理念延伸到了多 GPU 和 MoE 本地推理。它加上了基于 QTIP 的 EXL3 量化格式、面向消费级硬件的灵活张量并行和专家并行推理、经由 TabbyAPI 的 OpenAI 兼容服务器、连续动态批处理,以及多模态支持。

当你有 2-4+ 张消费级 NVIDIA GPU、或想跑本地 MoE 时,V3 很有吸引力。但要有心理准备:有些模型在 ExLlamaV3 里不支持张量并行或专家并行。

结论: ExLlamaV2 是发烧友的本地 CUDA 引擎。ExLlamaV3 是多 GPU(2-4 张)本地配置的前沿。能力更强,但棱角也更多。

vLLM:默认的开源生产级服务器

vLLM 是大多数团队做正经开源 LLM serving 时,第一个应该评估的引擎。

它提供基于 PagedAttention 的 KV 内存管理、连续批处理、分块预填充、前缀缓存、CUDA/HIP graph、广泛的量化支持(FP8、MXFP8/MXFP4、NVFP4、INT8、INT4、GPTQ、AWQ、GGUF)、优化过的 attention 和 GEMM/MoE kernel、推测解码、torch.compile,以及分离式的 prefill/decode/encode。

它也很灵活:张量 / 流水线 / 数据 / 专家 / 上下文并行、流式输出、结构化输出、工具调用、OpenAI 兼容和 Anthropic Messages API、gRPC、multi-LoRA,并支持 NVIDIA、AMD、x86/ARM/PowerPC CPU,外加面向 TPU、Gaudi、Ascend、Apple Silicon 等的插件。

vLLM 的文档指出,多节点部署通常用 Ray,而且没有 NVLink 时流水线并行可能胜过张量并行。陷阱在于以为 vLLM 免除了你做系统思考的必要。你仍然得调批处理、上下文长度、GPU 内存利用率、并行布局和路由。vLLM 给了你一个非常好的引擎;它仍然需要良好的系统设计(System Design)。

结论: 要是有人说「我们得在生产里跑开源模型」,vLLM 就是默认的起点。

SGLang:vLLM 那位系统脑的表亲

当 serving workload 变得很难看时——结构化输出、长上下文、MoE、分离、路由——你伸手去够的就是 SGLang。

它提供 RadixAttention 前缀缓存、prefill-decode 分离、推测解码、连续批处理、paged attention、张量 / 流水线 / 专家 / 数据并行、结构化输出、分块预填充,以及 multi-LoRA 批处理。它支持 NVIDIA、AMD、Intel Xeon、Google TPU、Ascend NPU 等等。

SGLang 的差异化在于 serving 架构。它的 prefill-decode 分离,把计算密集的 prefill 和内存密集的 decode 拆进各自专门的实例,并在两者之间传输 KV cache。这能防止漫长的 prefill batch 打断 decode、让 token 延迟飙升。

结论: SGLang 适合那些瓶颈已经不再是「我们能不能跑起这个模型?」,而是「我们能不能在恶劣流量下跑它,而不烧穿延迟、内存和成本?」的团队。

TensorRT-LLM:NVIDIA 性能的极致

TensorRT-LLM 是 NVIDIA 性能极致的技术栈。它优化到位、高度专门化、强大,而且根本不假装自己可移植。

它提供 Python API 来构建带有顶尖优化的 TensorRT 引擎,外加 Python 和 C++ 运行时。它包含为 attention、GEMM 和 MoE 定制的 kernel;prefill-decode 分离、宽专家并行(Wide Expert Parallelism)、推测解码;以及一个与 NVIDIA Dynamo 和 Triton Inference Server 集成的高层 Python API。

B200 GPU 能用优化过的 kernel 加载 FP4 权重。H100 及之后的卡支持 FP8 量化,相比 16-bit 能在精度损失极小的情况下让性能翻倍、内存占用减半。

它的强项:H100/H200/B200/GB200/GB300 级别的机群、纯 NVIDIA 数据中心、FP8/FP4 部署、多节点 serving,以及大规模 MoE。它的别扭之处:AMD、Apple 或 Intel 的可移植性;快速变动的实验性模型;小型本地配置;以及那些需要「在所有东西上都能跑」的团队。

结论: 要是你已经押注 NVIDIA、又在乎绝对性能,那 TensorRT-LLM 该进你的对比评测(bake-off)。你拿可移植性换性能。调校得专、但功能更少。

其余的选手

TGI 是 Hugging Face 的生产级服务器,带 tracing、指标、张量并行和连续批处理。当 HF 集成和简洁性很重要时用它。

MLC LLM 是编译器优先的通用部署引擎,跨 REST、Python、JavaScript、iOS 和 Android 提供 OpenAI 兼容 API。最适合「把 LLM 部署到一切地方」,尤其是浏览器、移动端和原生应用。

ONNX Runtime GenAI 在 ONNX Runtime 之上实现了完整的生成循环,并驱动着 Foundry Local、Windows ML 和 VS Code AI Toolkit。它支持 CPU、CUDA、DirectML、TensorRT-RTX、OpenVINO、QNN、WebGPU 和 AMD GPU。最适合应用部署和 ONNX 工作流。

OpenVINO GenAI 是面向 Xeon CPU、Arc GPU、Core Ultra 和 NPU 的 Intel 优化方案。它提供带连续批处理和 paged attention 的 OpenAI 兼容 serving。最适合 Intel 硬件。

LMDeploy 是一套聚焦 CUDA 的工具箱,用 TurboMind 追求性能、用 PyTorch 追求易用。对那些想要 vLLM/SGLang/TensorRT-LLM 之外另一选择的 CUDA 用户最有意思。

NVIDIA Dynamo 是坐在 vLLM、SGLang、TensorRT-LLM 这类引擎之上的分布式编排层,支持分离、智能路由和多级 KV 缓存。当单引擎 serving 不够用时用它。

注意:不要用 Ollama。

硬件策略配方

纯 CPU 服务器: llama.cpp 优先。Intel Xeon 用 OpenVINO。应用 / ONNX 部署用 ONNX Runtime GenAI。

MacBook / Mac Studio: Mac 原生工作流用 MLX / MLX-LM。GGUF 可移植性用 llama.cpp。

单张 RTX 3090 / 4090 / 5090: EXL2 本地推理用 ExLlamaV2。GGUF 或可移植性用 llama.cpp。要服务多个用户就上 vLLM。

双卡或四卡消费级 RTX 机器: 多 GPU 量化推理或 MoE 用 ExLlamaV3。在意 serving 行为就用 vLLM。要测路由或长上下文模式就用 SGLang。

8×H100 / H200 节点: 从 vLLM 或 SGLang 起步。如果纯 NVIDIA 且性能值得花时间调校,就给 TensorRT-LLM 跑个 benchmark。当多节点编排变得必要时用 Dynamo。

B200 / GB200 / GB300 级基础设施: 给 TensorRT-LLM、SGLang 和 vLLM 都跑 benchmark。加上 Dynamo 做机群级编排、KV 感知路由和自动扩缩。

AMD MI300 / MI325 / MI350 / MI355: 在 ROCm 上从 vLLM 或 SGLang 起步。别想当然以为 NVIDIA 的 benchmark 能干净地迁移过来。

Intel Xeon / Core Ultra / Arc: OpenVINO GenAI 或 OpenVINO Model Server。在意应用内嵌就用 ONNX Runtime GenAI。

浏览器、移动端、应用原生: MLC LLM / WebLLM 或 ONNX Runtime GenAI。

Benchmark:该测什么

糟糕的 benchmark:「我跑到了 180 tok/s。」

好的 benchmark 包含:

模型: 确切的模型、架构、参数量、MoE 激活参数量。

权重: dtype、量化格式、group size、校准(calibration)。

引擎: 版本、commit、后端、flag。

硬件: GPU SKU、内存容量、带宽、互联、CPU、RAM。

Workload: 输入/输出长度分布、并发、流式、共享前缀、结构化输出。

指标: TTFT、TPOT、端到端延迟、p50/p95/p99、每秒 token 数、每秒请求数、GPU 内存占用、KV cache 命中率、prefill 吞吐、decode 吞吐、每百万 token 成本。

Benchmark 准则:

  1. 永远别只用单用户的每秒 token 数去比较引擎。

  2. 测你实际的 prompt 和输出分布。

  3. 用真实的并发去测。

  4. 把 prefill 和 decode 分开测。

  5. 盯 p95 和 p99,不要只看平均值。

  6. 在目标上下文长度下测量内存余量。

  7. 如果你的应用有重复前缀,测缓存复用。

  8. 单独 benchmark 结构化输出;语法(grammar)会带来开销。

  9. 单独 benchmark LoRA 和 multi-LoRA。

  10. 在驱动、CUDA、ROCm、模型或引擎升级后重新测一遍。

常见错误

只按 VRAM 容量来选。 VRAM 决定能不能装下。带宽和调度器决定速度。一台大统一内存机器能装下巨大的模型,但当模型装得下时,H100 因为高得多的 HBM 带宽而 decode 得更快。

在弱互联上用张量并行。 没有 NVLink 或 NVSwitch 时,测一下流水线并行。vLLM 的文档对 L40S 这类配置专门点了名。

忽视 KV cache。 长上下文和并发会让 KV cache 成为限制因素。PagedAttention、前缀缓存、KV 量化和分离,在大规模下不是可选项

把本地引擎当生产级服务器。 llama.cpp 服务器很能干。MLX-LM 服务器很方便。Ollama 很讨喜,但不该拿来用

然而,生产意味着安全、可观测性、背压(backpressure)、路由、自动扩缩和 SLA 行为。MLX-LM 自己就警告说它的服务器不建议用于生产。

以为每种量化格式都可移植。 GGUF、EXL2、EXL3、AWQ、GPTQ、FP8、FP4、MLX 格式和 ONNX 之间并不能互换。对的格式,是你的引擎为之做了优化 kernel 的那一个。

忽视模型架构。 稠密(dense)模型、MoE、混合 attention、多模态模型和长上下文变体,压的是引擎的不同部位。「广泛支持」不代表每项优化都同样有效。

不看 workload 形态就信 benchmark 图表。 一张 Llama 3.1 8B 在 1K 输入 / 128 输出下的图表,对一个跑 Qwen 3.6 27B / Gemma 4 26B-A4B、上下文 80K 的编码 agent,或者一个有 500 并发用户的 RAG 服务,几乎说明不了什么。

带个人观点的最终地图

本地 AI 用户: 图方便用 LM Studio 或 Harbor。要掌控力用 llama.cpp。Mac 上用 MLX。CUDA 本地性能用 ExLlamaV2/V3。

搭一个本地 agent: 哪个都行,但按多数人实际在用的来说:可移植性用 llama.cpp。用户在 Apple Silicon 上就用 MLX。要在本地模拟生产级 serving 就用 vLLM。

服务一个内部团队: 从 vLLM 起步。如果结构化输出、长上下文、multi-LoRA、MoE 或路由很重要,就用 SGLang。

大规模服务客户: 给 vLLM、SGLang 和 TensorRT-LLM 都跑 benchmark。如果路由和分离很重要,SGLang 和 Dynamo 值得关注。

NVIDIA 数据中心: 极致性能用 TensorRT-LLM。灵活性用 vLLM。复杂 serving 用 SGLang。机群编排用 Dynamo。

Apple Silicon: 原生开发用 MLX。GGUF 用 llama.cpp。统一内存是一种容量上的超能力,但带宽上有取舍,它不是 HBM。

边缘、应用、浏览器或 Windows 原生: 视技术栈而定,用 llama.cpp、MLC LLM、ONNX Runtime GenAI 或 OpenVINO。

最终原则

推理引擎是有后果的。

在回答完下面这些问题之后,再去挑引擎:

  1. 我实际有什么硬件?

  2. 模型装得进快速内存,还是只装得进系统/统一内存?

  3. 瓶颈是 decode 还是 prefill?

  4. 哪种上下文长度和并发才是要紧的?

  5. prompt 之间是否共享得足够多,能吃到前缀缓存?

  6. 模型是稠密、MoE、多模态,还是混合的?

  7. 我需要的是本地的便利、生产级 serving,还是机群编排?

  8. 在我的目标引擎上,哪种量化格式有优化过的 kernel?

  9. 我的互联是 PCIe、NVLink、NVSwitch、Ethernet、RDMA,还是 Thunderbolt?

  10. 我优化的是延迟、吞吐、成本、隐私、可移植性,还是开发速度?

引擎,跟着这些答案走。

下次再见。

-Ahmad