本地推理的选型难点,表面看是"挑硬件",实质是"建度量"。因为没有统一的度量口径,任何性能数字都无法跨配置比较,选型就退化成比大小。
近期一个公开的本地推理配方库提供了一个很好的样本:截至 11 月 5 日,收录 770 条配置,每条均可溯源。它的价值不在于数字本身,而在于用一套数据结构把"不可比"变成了"可控比"。这篇按数据治理、容量模型、计算模型、引擎分层、度量规范五个层面分析。
一、数据治理层:来源分级是可比较性的前提
任何性能数据集,第一件事是标注可信度,否则汇总即噪声。该库的做法是四级标注:
| 等级 | 定义 | 可信度依据 |
|---|---|---|
| 官方 | 厂商自行发布 | 有发布主体,但通常为优选配置 |
| 实测 | 录入者自跑 | 附日志或截图,可复现性最强 |
| 转述 | 二手引用 | 无日志,链路可能失真 |
| 宣称 | 无来源说法 | 仅作线索,不作依据 |
配套还有一条工程原则值得借鉴:未知字段写 null,不做估算。 结果是 770 条记录中有 704 条缺命令行、332 条缺上下文长度——这不是数据质量问题,而是诚实标注的必然结果。同时,实测 465 条、宣称 178 条,两者的比例本身就说明该数据集的成熟度。
从架构视角看,这是一个典型的"不可变事实 + 分级标注"设计:原始数值不动,可信度作为独立维度附加。任何性能数据库都应当采用这一结构,否则汇总平均值会毫无意义。
二、容量模型层:两笔占用必须分开算
容量规划的第一步是把内存占用拆成两项独立预算。
第一项是权重。 估算式很稳定:
权重占用 ≈ 参数量 × 每权重比特数 ÷ 8
以 27B 稠密模型为例:
| 精度 | 每权重比特 | 权重占用 |
|---|---|---|
| BF16 | 16 | 约 54GB |
| 8bit | 8 | 约 27GB |
| 4bit | 4 | 约 14GB |
| 2bit | 2 | 约 7GB |
| 三值 | 1.58 | 约 5GB |
从 BF16 到 4bit,占用降到约四分之一——这是 4bit 成为工程默认档的直接原因:体积大幅下降,量化损失仍可接受。继续下压则进入收益递减区:权重精度分布的统计(4bit 261 条、3bit 117 条、2bit 106 条、1bit 28 条)清晰反映了实践者的谨慎程度。3bit 以下必须用自己的任务集做验收,不能只信基准。
第二项是 KV 缓存。 权重是静态占用,KV 是动态占用,且随上下文长度线性增长。两者共享同一池显存,属于竞争关系。库里有一条 5060 Ti 配 262K 上下文的记录,权重 7.9GB——是否可行取决于剩余空间能否承载 KV,必须自行核算。
此外,MoE 架构需要区分两个参数量:
| 模型 | 总参数 | 每 Token 激活 |
|---|---|---|
| Qwen3.8-Flash-Next | 125B | 6B |
| DeepSeek-V4.1-Flash | 552B | 16B |
容量按总参数算,速度按激活参数看。 混算会导致双向误判:既可能高估显存需求,也可能低估单次推理成本。
三、计算模型层:容量、带宽、算力三个约束
硬件评估需要三个独立维度,不能合并成一个"性能"指标:
- 容量:决定能装下多大的模型
- 带宽:决定解码速度(逐 Token 生成)
- 算力:决定预填充速度(批量摄入提示词)
预填充与解码是两种截然不同的负载,在实践中常被混用。同口径的预填充实测数据(约数):
| 硬件 | 预填充速度 |
|---|---|
| RTX 5090 | 约 5247 tok/s |
| RTX 3090 | 约 2000 tok/s |
| RTX 4090 | 约 887 tok/s |
| Strix Halo | 约 699 tok/s |
| Mac mini M4 Pro | 约 190 tok/s |
这张表最值得注意的不是绝对值,而是排序关系与解码排序并不一致。小尺寸设备在预填充上衰减更明显,因为该环节对算力而非带宽敏感。选型时必须先判断负载类型:长文档摘要类任务看重预填充,多轮短对话看重解码带宽。
从数据分布看,硬件生态的重心也很清楚:NVIDIA 消费卡 264 条、Mac 178 条、DGX Spark 147 条、AMD 87 条、二手数据中心卡 37 条、其他 57 条。消费卡占主体,说明本地推理的主流场景仍是中小规模私有部署。
四、引擎层:同一硬件的能力放大器
引擎对性能的影响容易被低估。一个直接对照:同一张 5060 Ti、同一个 Qwen3.8-27B,llama.cpp 为 32 tok/s,ExLlama 为 66 tok/s。硬件与模型完全一致,仅更换引擎即翻倍。
各引擎的定位可以按适配条件分层:
| 引擎 | 核心定位 | 适配场景 |
|---|---|---|
| llama.cpp | 通用覆盖,GGUF 格式 | 优先跑通,跨 CPU/CUDA/ROCm/Vulkan/Metal |
| vLLM / SGLang | 服务化推理 | 多路并发、连续批处理 |
| MLX / cMLX | 苹果芯片专用 | Apple Silicon 本地部署 |
| ExLlama | GPU 量化加速 | 单机吞吐优先 |
| Strata | MoE 专家分层卸载 | 显存装不下,需跨显存/内存/SSD |
选型逻辑应遵循"平台 → 形态 → 容量"三步:先确认平台支持(是否存在对应后端),再确认部署形态(单机还是服务化),最后确认容量是否满足(不满足则选支持卸载或分层的引擎)。
五、度量规范层:口径必须结构化
这是整个体系里最容易失控的一环。同一模型、同一硬件,改变测量方式即可造成一倍差异。
一个典型样本:某 DeepSeek-V4.1-Flash 配置(2× DGX Spark、TensorFold、4B 权重、400K KV、8 槽位)记录了三个数字——单流 55.4 tok/s、八路并发 103.5 tok/s、首 Token 延迟 0.19–0.26s。三者描述的是不同维度,不可互相替代。
结构性问题在于:770 条记录中 265 条的并发字段为空,即多数配方仅提供单流数据。同时,汇总值与官方值也存在系统性差异(如 134.8 对比 202.7),源于统计方式而非造假。
因此,度量口径应当作为数据结构的一部分被强制记录,建议至少包含四项:
- 并发度(单流 / 多路,注明路数)
- 输入长度(提示词 Token 数)
- 输出长度(生成上限)
- 采样设置与统计方式(温度、重复次数、取中位还是均值)
缺少任何一项,该数字就只能作为线索,不能作为容量规划或采购依据。
六、决策流程:顺序决定了成本
把上述五层串起来,可得到一条确定性的选型流程:
- 定义负载与口径:单用户还是多用户、提示长度、输出长度。这一步决定后续所有判断的基准。
- 确定模型形态:稠密或 MoE、总参数、激活参数、目标上下文。
- 核算权重容量:按公式计算,得到静态占用。
- 叠加 KV 预算:按目标上下文留出余量,避免占满。
- 匹配硬件:在容量满足的候选中,按带宽与算力权衡,兼顾采购成本。
- 选择引擎并复测:在目标平台上用统一口径实测,取多次中位数。
这个顺序的价值在于:前三步是纯计算,不花钱就能排除大部分不可行组合;后三步才涉及采购与部署。
七、参照基准:把绝对速度放回体感
最后需要一组外部参照,避免内部指标自我循环。云上服务的公开数据约为:Claude Sonnet 5.5 约 103 tok/s,GPT-5.5 约 84 tok/s。而人默读英文的速度约为每秒 4 个词。
这意味着本地达到约 50 tok/s 即可满足日常对话体验。除非面向批量生成或服务化并发,追求极端峰值没有实际收益——峰值通常来自"极小激活 MoE + 极致量化"的组合,迁移到真实任务上未必成立。
小结
本地推理的选型本质是度量工程:先建立可信的数据分层,再建立双账容量模型,然后区分计算约束,最后把口径结构化。 速度是这些条件的结果,不是起点。任何一条配方,都应先看来源等级,再看口径,最后在目标环境复测一次。