# 推理工程从入门到精通

Reddit r/LocalLLaMA 工具

摘要

# LLM 推理优化实用指南:在硬件约束下榨干性能 本文是一份面向实践者的指南,覆盖常见的推理瓶颈——包括运行时选型(Ollama、llama.cpp、vLLM、SGLang)、硬件相关的编译选项、量化方案的选择(IQ vs Q_K vs NL),以及按任务选型模型——并给出在有限硬件条件下优化 LLM 推理的最佳实践。 --- ## 目录 1. [为什么推理是瓶颈](#为什么推理是瓶颈) 2. [运行时选型:Ollama、llama.cpp、vLLM、SGLang](#运行时选型) 3. [硬件相关的编译选项](#硬件相关的编译选项) 4. [量化方案:IQ vs Q_K vs NL](#量化方案) 5. [按任务选择模型](#按任务选择模型) 6. [端到端最佳实践](#端到端最佳实践) 7. [常见误区与排查清单](#常见误区与排查清单) --- ## 为什么推理是瓶颈 推理的成本通常由两部分构成: - **预填充阶段(prefill)**:处理输入 prompt,计算量大,受算力(FLOPs)限制,是 **compute-bound**。 - **生成阶段(decode)**:逐 token 自回归生成,每步都要读取全部权重,受内存带宽限制,是 **memory-bandwidth-bound**。 在 decode 阶段,实际算力利用率往往只有个位数百分比,性能几乎完全由 **「模型大小 / 内存带宽」** 决定。因此: > 量化带来的收益不只是"显存更省",更重要的是"每步读的数据更少,生成更快"。 理解这一点,是理解后续所有优化手段的基础。 --- ## 运行时选型 没有万能的推理引擎,选择取决于场景:本地单用户、批量离线处理,还是高并发在线服务。 ### Ollama - **定位**:本地开发与个人使用,开箱即用。 - **优点**:安装简单、模型管理便捷、内置轻量 HTTP API、自动选择合理的量化版本。 - **缺点**:抽象层较多,难以做细粒度调优;并发能力有限。 - **适用**:开发者本机实验、原型验证、单用户交互场景。 ### llama.cpp - **定位**:CPU / 边缘设备推理的事实标准,也可用于 GPU。 - **优点**:编译选项极其丰富、内存占用低、跨平台支持好(x86、ARM、Apple Silicon)、量化格式最全。 - **缺点**:批量与并发支持不如 vLLM;高并发吞吐不是强项。 - **适用**:树莓派、MacBook、老旧 CPU 服务器、需要极致内存控制的场景。 ### vLLM - **定位**:面向生产的高吞吐在线推理服务。 - **优点**:PagedAttention、Continuous Batching、Tensor Parallelism、丰富的量化后端支持,高并发下吞吐优势显著。 - **缺点**:资源开销较大、单用户低延迟场景未必占优、需要 GPU。 - **适用**:API 服务、多租户推理平台、需要稳定吞吐的生产环境。 ### SGLang - **定位**:复杂采样工作负载与多轮对话的高吞吐引擎。 - **优点**:RadixAttention 对共享前缀缓存极高效,擅长多轮对话、工具调用、结构化输出等场景;支持混合并行与投机解码。 - **缺点**:生态相对年轻,调试资料略少于 vLLM。 - **适用**:多轮 agent、共享系统提示的高并发服务、复杂控制流的 LLM 应用。 ### 选型速查表 | 场景 | 推荐 | | --- | --- | | 个人本机 / 开发调试 | Ollama、llama.cpp | | 边缘 / CPU / 低内存设备 | llama.cpp | | 高并发在线 API | vLLM | | 多轮对话 / Agent / 共享前缀 | SGLang | | 批量离线处理 | vLLM 或 SGLang(大 batch 时均可) | --- ## 硬件相关的编译选项 "用同样的模型和同样的量化,不同机器的性能可以差几倍"——差别的来源往往就是编译选项。 ### CPU(llama.cpp) 在 `CMake` 构建时根据 CPU 指令集开启对应选项: | 构建选项 | 说明 | | --- | --- | | `-DGGML_NATIVE=ON` | 按当前编译机器的 CPU 指令集自动生成代码 | | `-DGGML_AVX=ON` / `-DGGML_AVX2=ON` / `-DGGML_AVX512=ON` | 启用对应 SSE/AVX/AVX-512 加速 | | `-DGGML_ARM_NEON=ON` | ARM NEON 加速(默认启用) | | `-DGGML_CUDA=ON` / `-DGGML_METAL=ON` / `-DGGML_VULKAN=ON` | 对应 GPU 后端 | 要点: - **在目标机器上编译**,`GGML_NATIVE=ON` 才能选出最优指令集。 - AVX-512 相比 AVX2 在大模型推理上常有明显提升,务必确认是否开启。 - 大矩阵乘法优先走 BLAS(如 OpenBLAS、MKL),可显著提升 prefill 吞吐。 ### GPU - **CUDA**:确保 `CMAKE_CUDA_ARCHITECTURES` 或 `-DCMAKE_CUDA_ARCHITECTURES=native` 与你的 GPU 匹配,避免 PTX JIT 带来的启动开销。 - **Compute capability 对齐**:`nvcc` 编译的代码若高于 GPU 的 compute capability,可能直接无法运行。 - **Tensor Core**:确认量化内核能真正利用 Tensor Core(如 AWQ、GPTQ 的 Marlin 内核、FP8 内核),而不是退化到普通 CUDA 核心。 ### Apple Silicon - Metal 后端通常比 CPU 后端快 10 倍以上。 - 统一内存架构下,量化收益不仅体现在速度,还体现在模型容量上限。 --- ## 量化方案 ### 量化格式速览 | 类型 | 代表格式 | 位宽 | 特点 | | --- | --- | --- | --- | | **整数量化** | Q8_0、Q6_K、Q5_K_M、Q4_K_M、Q4_0 | 4–8 bit | 简单高效,广泛兼容 | | **K-Quant(Q_K)** | Q4_K_M、Q5_K_M、Q6_K、Q3_K_L | 3–6 bit | 逐层/逐块混合精度,是当前主流推荐 | | **重要性量化(IQ)** | IQ2_XXS、IQ3_XXS、IQ4_XS | 2–4 bit | 基于重要性矩阵(imatrix)的方法,低比特下质量更稳 | | **NL / 非线性量化** | NF4(bitsandbytes)、非线性 K-quants | ~4 bit | 均匀分布假设被打破,对非均匀权重分布更友好 | ### IQ(Importance Quantization) - 通过 **imatrix**(重要性校准数据集)为每个权重组赋予重要性权重,量化误差大的权重保留更多信息。 - 在 **3–4 bit** 低比特场景下,质量损失通常明显小于传统 Q 格式。 - 代价:生成 imatrix 需要校准数据集;部分格式推理速度略慢。 - **推荐**:在显存/内存吃紧、必须用 2–4 bit 时优先考虑 IQ 系列。 ### Q_K(K-Quant) - llama.cpp 中的主力格式,采用**分层混合精度**策略:对敏感层用更高位宽,非敏感层用更低位宽。 - `Q4_K_M` 是当前性价比最均衡的选择,`Q5_K_M` / `Q6_K` 则提供接近 FP16 的质量。 - **推荐**:大多数场景的默认选择。Q4_K_M 用于 8–16 GB 内存的机器,Q6_K 用于追求质量且内存尚可的机器。 ### NL(非线性量化) - NF4 等格式基于权重分布近似正态的先验,将量化区间做**非线性映射**,低比特下保真度更高。 - 在 bitsandbytes 生态中支持良好,但与 llama.cpp / GGUF 生态的兼容性有限。 - **推荐**:在 HuggingFace transformers 直接微调/推理、且可用 bitsandbytes 时使用;若走 GGUF / llama.cpp / vLLM 部署链路,K-Quant 或 IQ 更实用。 ### 选型建议 | 内存预算 | 推荐方案 | | --- | --- | | 充裕 | 不量化 / FP16 / BF16,或 Q8_0 | | 中等 | Q6_K、Q5_K_M | | 紧张(12–16 GB) | Q4_K_M(首选) | | 极紧(< 12 GB,大模型) | IQ4_XS、IQ3_XXS,或 Q3_K_L | | 最紧(2–3 bit) | IQ2_XXS(需 imatrix) | > **通用原则**:量化是"用质量换速度与容量"。每换一个更激进的格式,都要用**你的真实任务**做回归测试,而不是只看通用 benchmark。 --- ## 按任务选择模型 "最好的模型"取决于任务类型。 | 任务类型 | 关注点 | 建议 | | --- | --- | --- | | **通用对话 / 助手** | 指令跟随、事实准确性、长上下文 | 通用 instruct 模型(如 Llama、Qwen、Mistral 系列),质量优先,量化可保守 | | **代码生成** | 语法正确性、长上下文代码理解 | 代码专精模型;建议 Q5_K_M 及以上,低比特对代码影响较大 | | **摘要 / 分类 / 提取** | 输出短、延迟不敏感、可能需要低延迟 | 可大胆用低比特模型甚至更小的模型,量化到 Q4 甚至 IQ3 通常可接受 | | **数学 / 推理** | 逻辑链长度、token 敏感 | 推理增强型模型;量化影响更显著,尽量 Q6_K 以上 | | **RAG / 长文档** | 上下文长度、KV cache 体积 | 考虑支持长上下文的模型 + KV cache 量化(如 k-quant 的 KV cache、Q8 KV) | | **Agent / 工具调用** | 结构化输出稳定性、多轮一致性 | 使用原生支持 tool calling 的模型;避免过度量化 | | **边缘 / 离线** | 小模型、低延迟、无网络 | 紧凑型模型(3B–8B)+ IQ/Q4 格式 | 模型规模的取舍: - **小模型(1B–3B)**:延迟最低、成本最低,适合分类、改写等"短任务"。 - **中模型(7B–14B)**:质量与速度的甜点区,绝大多数场景够用。 - **大模型(30B+)**:复杂推理与长任务才值得,对硬件要求高。 > **务实建议**:先用小模型跑通 pipeline,测量真实指标(准确率、延迟、token/s),再决定是否升级模型规模。模型翻倍带来的收益,常常不如一个更好的量化方案或正确的引擎配置。 --- ## 端到端最佳实践 ### 1. 先测量,再优化 建立可复现的基准: - 用**你的真实请求**做测试,不要只用通用 benchmark。 - 分开测量 prefill 速度与 decode 速度。 - 关注 **首 token 延迟(TTFT)** 与 **每 token 延迟(TPOT)**,二者对应不同瓶颈。 ### 2. 针对瓶颈优化 | 症状 | 可能瓶颈 | 优化方向 | | --- | --- | --- | | prefill 慢、decode 正常 | compute-bound | 更大 batch、更好硬件、Flash Attention | | decode 慢、prefill 正常 | 内存带宽受限 | **更小的量化格式**、更快的显存/GPU、投机解码 | | 内存溢出 | KV cache / 模型过大 | 量化 KV cache、更激进的模型量化、更小模型 | ### 3. 高并发场景的关键手段 - **Continuous Batching**:让请求动态进出批次,显著提升吞吐(vLLM、SGLang 内置)。 - **Paged KV Cache**:减少显存碎片,提高并发容量。 - **Prefix / Radix Caching**:共享 system prompt 与多轮对话前缀的 KV(SGLang 的 RadixAttention 尤其强)。 - **Tensor / Pipeline Parallelism**:多卡场景下的显存与算力切分。 - **Speculative Decoding**:用小模型起草、大模型验证,decode 吞吐可提升 2–3 倍。 ### 4. 减少生成量本身 很多时候最大的优化不是引擎,而是**少生成一点**: - 精简 system prompt 与 few-shot 示例。 - 使用 `max_tokens` 硬限制与合理的 `temperature`。 - 对摘要/分类任务采用结构化输出,减少冗长自由文本。 --- ## 常见误区与排查清单 ### 误区 - ❌ "量化 = 模型变笨"。Q4_K_M 通常只带来很小的质量损失,收益是显著的速度与容量提升。 - ❌ "引擎越复杂越好"。本地单用户用 vLLM 往往是浪费;反之,高并发用 Ollama 会严重限制吞吐。 - ❌ "看别人 benchmark 选型"。别人的 GPU、上下文长度、batch size 与你不同,结论可能完全相反。 - ❌ "只调模型不调编译"。同一模型在不同 CPU 指令集下可以差 2–4 倍。 ### 排查清单 - [ ] 量化格式是否真的被目标引擎支持并能加速? - [ ] KV cache 占用是否计入内存预算? - [ ] batch size 是否已调优?(小 batch 可能远未打满 GPU) - [ ] 上下文长度设置是否合理?(KV cache 随长度线性增长) - [ ] 是否启用了正确的 Flash Attention / Paged Attention? - [ ] CPU 推理是否用上了 BLAS? - [ ] GPU 架构是否与编译时设置一致? - [ ] 是否用真实任务做过质量回归测试? --- ## 结语 优化 LLM 推理没有银弹,但有一条清晰的路径: 1. **明确场景**——本地开发、边缘部署,还是高并发服务。 2. **选对引擎**——Ollama / llama.cpp / vLLM / SGLang 各有其位。 3. **匹配硬件**——编译选项与并行策略要与你的 CPU/GPU 对齐。 4. **合理量化**——Q_K 是默认,IQ 用于极限压缩,NL 留给特定生态。 5. **按任务选模型**——别为短任务付长模型的代价。 6. **持续测量**——用真实负载回归,而不是盲信通用 benchmark。 把这六步走通,你就能在给定的硬件约束下,获得既快又稳的推理性能。

大家好!我是一名前软件工程师(SWE),最近转型做了推理工程师。几个月前我启动了一个副业项目,如今由于需求过于旺盛,我已经全职投入其中。这真是一个难得的机会,因为优化运行时的人远少于构建应用或提供 AI 方案的人。所以我一直在潜水关注这个社区,注意到很多人在硬件配置上存在严重的次优化问题,我把其中最大的几类错误归纳成了几个板块。本指南的目的在于揭示常见的推理瓶颈,并在你的硬件约束范围内提供最佳实践。 # 运行时 ## 一、选择正确的运行时 这是我看到的最大错误。为你所使用的架构和模型选择正确的运行时,是最关键的决定。一般来说,以下规则可以帮助你确定该用哪个运行时: 首先,Ollama 永远不是最优选择,它只是最简单的。如果你想要快速上手、操作简便,且有多余的 RAM,它是个不错的起点。它对用户非常友好,需要的配置也更少。但它无法提供最佳的推理速度。 如果你的模型需要 CPU 卸载(CPU offload),那么 llama.cpp 是你的最佳选择。如果不需要,而是纯 GPU 运行,VLLM 很可能提供最好的结果。90% 的情况下就是这么简单。 如果你的工作负载涉及 Langgraph,SGLang 可能值得考虑,因为它针对该工具链做了高度优化。否则,请坚持使用上述方案。主分支(mainline branches)是最佳选择,社区分支仅在高度小众的场景下有性能增益(例如针对特定模型或配置),但通常优化不足且维护不佳。 ## 二、优化与维护运行时 人们在运行时方面的另一个重大错误是没有针对具体硬件进行编译。这里不打算逐一列出所有编译标志,Google 可以帮你。只需搜索"使用 [GPU、CPU、RAM 类型] 编译 [运行时] 的最优编译标志"。 最容易被遗漏的标志通常是针对特定架构的优化,这些至关重要。 只要发生以下*任何*情况,运行时都应该用最优标志重新编译: - 系统更新 - 内核/驱动更新 - 运行了一个比你上次编译更晚发布或修改过的模型 - 超过一个月没有重新编译(近期更新通常包含内核或路径优化) # 模型选择 ## 一、量化(Quantization) 量化——多大的词啊,意义却少得可怜。你只需要知道它能让模型变小就够了。 量化格式有无数种 Q_K_X_&$&$&$,我不会逐一讲解,而是提供基本的原则: - IQ 系列量化在同等体积下通常是最佳选择。如果你在 IQ4_XS 和 Q4_K_M 之间做选择,IQ4_XS 既占用更少的显存,复杂度也更高。 - 非线性(NL)量化只有在存在 CPU 卸载时才会更有优势。即便如此,IQ 量化相比 NL 量化往往能提供更多的上下文空间,因此更值得优先选择。 - 如果你遇到了一种从未见过的量化格式,请阅读相关文档。它极有可能是针对该特定模型高度优化的,也确实应该是你的选择。*对于自定义量化格式*,你去搜索或询问 ChatGPT *每次都会得到错误答案*。这类量化格式通常只出现在自定义调优过的模型中。 - 标准的 Q_K_M 量化在你运行该模型完全没有硬件约束时效果最好,因为路径优化是最佳的。但话说回来,如果没有硬件约束,你完全可以运行一个更好的模型。这种量化只适合用简单模型完成简单任务。 ## 二、任务(Task) 某些模型在特定任务上表现出色。这部分是主观的、基于个人偏好的,以下是我的清单: **编码**:走 API 的话,用 Anthropic,模型毫无疑问是最好的。Opus 和 Sonnet 5.5 在性能上都表现出色,且每个任务的低 token 消耗使它们比之前的版本更经济。DeepSeek 模型是性价比最高的选择。Qwen 模型在本地推理的各方面都是明确的赢家。 **写作**:技术写作用 Opus/Sonnet,创意写作用 Gemini。本地创意写作用 Gemma。 **视频**:本地场景下,多数情况用 Wan 2.2 就够用了。ChatGPT 和 Copilot 都提供了出人意料的免费图像/视频生成功能。付费方面 Veo 是最好的。 # 硬件 买一台预算型主机,或者自己用零件组装。我在所有类别、多个模型上,用一块 RTX 3060 加 128 GB RAM 榨出的性能超过了 DGX Spark。Spark 在稠密模型上有优势,但我在另一套配置上总体上能运行复杂度更高的模型,而价格只有它的五分之一。 AMD 和 Intel 在单位价格性能上明显落后,不过我听说 Intel 最近取得了一些重大突破。但我自己还没有验证过。 # 模型优化 ## 一、投机解码(Spec Decode)/ MTP - 如果你有 CPU 卸载,投机解码会*永远*拖慢你的速度。除非至少有几百 Mb/s 的带宽,否则额外的开销计算不值得——而你的 CPU 达不到这个水平。 - MTP 有时是内置功能,有时则需要一个额外的辅助模型。确保你了解你的模型上它是如何工作的,以及应该运行哪些标志。 - 每个模型只会针对恰好 0 到 1 种投机解码方式做过优化。先弄清楚是哪一种(或者根本没有),而不是浪费时间去测试各种方法。 ## 二、模型调优 为了展示你能通过命令优化达到什么程度,下面是我运行 Qwen 3.8 Flash-Next(一个 156B 参数模型)的示例命令,使用 12 GB 显存(和 128 GB 内存),在 200k 上下文下实现 10 token/s 的解码速度和 150 token/s 的预填充速度: ``` ~/llama.cpp/build/bin/llama-server --flash-attn on --batch-size 1024 --ubatch-size 1024 --no-warmup --cache-reuse 256 --jinja --host 0.0.0.0 --port 8090 --presence-penalty 0.0 --repeat-penalty 1.0 -m ~/llama.cpp/LLM/Qwen3.8-Flash-IQ4_XS/UD-IQ4_XS/Qwen3.8-Flash-Next-UD-IQ4_XS-00001-of-00003.gguf --temp 0.95 --top-k 20 --top-p 0.97 --min-p 0.05 -np 1 --chat-template-kwargs '{"enable_thinking": true, "preserve_thinking": true, "reasoning_effort": "xhigh"}' --threads-batch 16 --threads 8 --gpu-layers 150 --n-cpu-moe 48 -c 200000 --override-tensor per_layer_token_embd.weight=CPU -ctv q8_0 -ctk q8_0 --cache-ram 8192 --checkpoint-min-step 512 --ctx-checkpoints 4 --kv-unified --reasoning-preserve --load-mode mmap+mlock ``` 命令很多对吧?这已经是你能应用的每一种可能的优化了。下面我逐条说明。虽然这是 llama.cpp 特定的,但你会发现其他运行时也有相同的标志,只是语法略有不同。 - **-flash-attn (-fa) on**:强制启用 Flash Attention 优化和路径。显式设置为 `on` 以覆盖任何回退(fallback)。如果模型较新、尚未被优化,`auto` 可能是最优选择。 - **--batch / --ubatch**:batch 是解码(decode)的分块大小,ubatch 是预填充(prefill)的分块大小。两者必须是彼此的整数倍,否则你会增加额外计算。对于 CPU 卸载场景,两者相等是理想情况;对于全 GPU 负载,batch 比 ubatch 高 2-4 倍是最优的。你需要反复调试这些值以达到最优。batch/ubatch 应为 2 的幂,以优化架构性能。以 256 为间隔进行测试通常就足够了。 - **--no-warmup**:防止模型进行初始加载探测,省去不必要的延迟。 - **--cache-reuse x**:指示模型以 x 个 token 为间隔复用缓存值并扫描相似性。 - **--jinja**:一个被严重低估且非常重要的标志。利用原生聊天模板 kwargs 来确保输出的一致性。 - **--presence-penalty**:对文本中已出现词语的固定惩罚率。主要用于创意写作,防止行文重复。 - **--repeat-penalty**:降低已使用 token 被重复使用的概率。最适用于防止思维代理(thinking agents)陷入死循环。 - **-temp**:模型温度——决定模型有多"有创意"。0 是完全确定性的,1 是自由发挥。 - **top-k**:硬性截断,只保留概率最高的前 k 个词。每个模型都会为思维/指令微调场景推荐 k 值。较低的 key 值可以减少幻觉,但代价是重复和创造力的损失。 - **top-p**:包含概率排名前 P 百分比的词汇…… (原文在此处截断)
查看原文

相似文章

本地LLM推理优化:完整指南

Reddit r/LocalLLaMA

一份关于在消费级硬件上优化本地LLM推理的全面指南,涵盖llama.cpp、vLLM和LM Studio等工具,并提供关于内存层次结构、层放置和常见故障模式的实用建议。

AI推理工程指南(阅读时间约17分钟)

TLDR AI

本指南解释了AI推理工程这一学科,涵盖了预填充和解码阶段的划分、从封闭模型到开放模型的转变,以及针对延迟、吞吐量和成本的优化技术。

过拟合推理引擎的崛起

Reddit r/LocalLLaMA

一篇博客文章论证称,高度专为特定硬件与特定模型定制的推理运行时(Strata、ninfer、DwarfStar、Splash、llamAmpere、gufo)如今在固定消费级硬件上的表现已超越 llama.cpp、vLLM、Ollama 等通用引擎,性能高出 2.5-4 倍;其中 Strata 在单张 12GB RTX 4070 上对 Qwen3.8-Flash-Next 的解码速度可达 53-90 tok/s。