0.8MB 跑通 Qwen|第 7-2 篇:推理引擎的混合精度路由——flags 决定谁用 Q8、谁用 Q4

简介: 本系列《0.8MB跑通Qwen》聚焦ARM端零依赖纯C推理引擎,适配Qwen3-VL多模态模型,在RK3588上实现实测。核心创新是混合精度路由:prefill阶段用Q8保精度,decode阶段用Q4省带宽,通过flags比特位动态调度,兼顾速度与质量。(239字)

系列:《0.8MB 跑通 Qwen:从零实现 ARM 零依赖纯 C 推理引擎》(30 天 × 90 篇) | 适配模型:Qwen3-VL-8B-Instruct(千问3_VL_8B_Instruct)· Qwen3-VL-2B-Instruct · Qwen3-30B-A3B | 测试设备:RK3588(4×Cortex-A76 + 4×Cortex-A55,aarch64)

系列总纲:《0.8MB 跑通 Qwen》30 天 90 篇 · 总纲(阿里云社区)

上一篇:7-1《Q4_0 格式:与 GGUF 对齐的 4bit 布局》 | 下一篇:7-3《预热与测量抖动》

真机实测通过:本文实验已在 RK3588 板端实测完成(2026-09;方法学与原始记录见仓库 docs 与《实验脚本》目录)

一句话导读:推理引擎的混合精度路由:flags 用比特位声明 Q8/Q4 双份副本,读 use_q4 判定与 prefill/decode 门控,讲清 prefill 走 Q8 保精度、decode 走 Q4 省带宽的取舍。

关键词:手搓 Qwen 推理引擎、千问大模型推理、Qwen3-VL、零依赖纯 C、混合精度、flags、Q8 量化、Q4_0、RK3588

导语:既然 Q4 的误差远大于 Q8,引擎为何不全用 Q8,也不全用 Q4?手搓 Qwen 推理引擎给出混合精度路由:文件头用 flags 的比特位声明 Q8/Q4 双份副本,运行期按 prefill 走 Q8 保精度、decode 走 Q4 省带宽来分流。这篇讲清这套路由的判断与落地。

7-1 说 Q4 的误差是 Q8 的 11 倍——那引擎为什么不全上 Q8?反过来,为什么又不全上 Q4?答案:不同的矩阵对精度的敏感度不同,对带宽的压力也不同。引擎用"双份权重 + 运行时路由"来同时吃到两种量化的好处。

1. 知识点:混合精度的两问

一个推理 step 里要跑几类矩阵:attention 的 Q/K/V/O、FFN 的 gate/up/down。它们问同一个问题,答案不同:

  1. 这层数值敏感吗? attention 的输出直接进 softmax,误差会被放大(softmax 是"赢家通吃"),所以 QKV 更想要 Q8;FFN 的 gate/up 是逐点激活(SiLU 之类),对量化误差宽容得多,可以 Q4。
  2. 这层带宽压力大吗? decode 每词重读权重(5-1),矩阵越大越希望字节少——FFN 的 gate+up 是模型里最大的矩阵,Q4 在这里省得最多。

所以理想形态是:每个矩阵按"敏感度"选精度。工程上落地成两件事:

  • 转换期:同一份权重存两份——Q8 副本 + Q4 副本(加个 flags 记着"这文件是混合的");
  • 运行期:按阶段路由——prefill 走 Q8(要把上下文算准),decode 走 Q4(省带宽)。

2. 对应代码:flags 与运行期路由

转换期:文件头的 flags 用比特位记录"有哪些副本"。看板端真实 model.vqf 的头部(Day 3 的 xxd 已经见过):

flags = 0x63
  bit0 VQF_FLAG_Q8_8X8  (1)  : 有 Q8 副本(8x8 布局)
  bit1 VQF_FLAG_Q4_4X4  (2)  : 有 Q4 副本(4x4 布局)
  bit5 VQF_FLAG_EMB_F16 (32) : embedding 存 F16
  bit6 VQF_FLAG_VISION  (64) : 含视觉张量
0x63 = 64+32+2+1 -> 同时声明了 Q8 与 Q4 副本 = 混合精度文件

引擎读头时若两个 bit 都置位,就知道这份权重是"双份"的,运行期才有得选。

运行期:真正的路由策略在 vllm_safetensors.c 第 10493–10495 行(及 11311–11312 行的同构代码):

/* Mixed precision: --prefill-q8 forces this prefill GEMM onto Q8_0 while
 * decode keeps Q4_0 (see g_st_prefill_q8). */
const int use_q4 = w->has_q4 && (!g_st_prefill_q8 || !w->q8_q_weight);

读法:在 prefill 的 GEMM 里,"用不用 Q4"取决于 --prefill-q8(默认开,g_st_prefill_q8=1,第 213 行):开了且 Q8 副本在 → 用 Q8;否则用 Q4。而 decode 侧的单 token GEMV 走 Q4 路径(第 3849 行起的 M4f)。一句话策略:prefill 用 Q8 保精度,decode 用 Q4 省带宽。

3. 改动后果:双份权重同台实测,读混合精度分档

引擎的 --bench-mixed 会拿同一份合成权重(dual Q8_0+Q4_0 copies)把 Q4/Q8 两套内核在 decode(M=1)与 prefill(M=32)都跑一遍。板端实测(RK3588 / 2026-09,当日一轮):

Weights: dual Q8_0+Q4_0 copies (273 MB)
--- Decode (M=1) ---
Q4 fused QKV         1.581 ms   31.8 GFLOPS
Q8 fused QKV (dec)   1.358 ms   37.1 GFLOPS     <- QKV:Q8 更快
Q4 fused gate+up     2.728 ms   73.8 GFLOPS
Q8 fused gate+up (dec) 4.765 ms 42.2 GFLOPS     <- gate+up:Q4 快 1.7x
Q4 fused down+res    1.285 ms   78.4 GFLOPS
Q8 fused down+res (dec) 1.985 ms 50.7 GFLOPS    <- down+res:Q4 快 1.5x
--- Prefill (M=32, batched) ---
Q4 batched QKV       5.370 ms  299.9 GFLOPS
Q8 batched QKV       5.782 ms  278.6 GFLOPS
Q4 batched gate+up  20.143 ms  319.8 GFLOPS
Q8 batched gate+up  22.425 ms  287.3 GFLOPS
Q4 batched down+res 10.884 ms  296.0 GFLOPS
Q8 batched down+res 11.592 ms  277.9 GFLOPS

这张表本身就是"混合精度为什么存在"的答案:

  • 形状差异:decode 里 QKV 窄、Q8 更快(37.1 vs 31.8 GFLOPS);gate+up/down+res 宽、Q4 快得多(73.8 vs 42.2、78.4 vs 50.7)——同一种精度在不同形状上输赢相反;
  • 相位差异:prefill(M=32)里 Q4 全面领先(300+ GFLOPS vs ~280),但引擎仍让 prefill 走 Q8——因为选 Q8 的理由是精度不是速度(bench 的合成权重没有"输出质量"可言,真实模型里 prefill 结果要喂后续 decode,误差要压住);
  • 注意数值会抖:同一轮 bench 内部是 best-of 的稳定读数,但跨轮/跨天会有 ±20% 级别波动(7-3 专门讲怎么读才可信)。

想亲手改路由:--prefill-q8 关掉(或让模型只有 Q4 副本)时,use_q4 恒真,prefill 也走 Q4——精度让位于带宽。真实模型上对比同 prompt 的输出即可观察差异(任务 4 给出姿势)。

4. 学员调试任务

  • A 档(板端动手):
    1. 解析你的 .vqf 头(Day 3 脚本),读出 flags 并逐位解释"有哪些副本";
    2. 跑一次 --bench-mixed,抄下 decode 与 prefill 的 Q4/Q8 分档表,标出"哪些格子 Q4 赢、哪些 Q8 赢";
    3. 若用 --prefill-q8 关掉再跑同一模型的一次短生成,与默认对比输出的 rel err(若有对拍基准)。
  • B 档(纯读源码):读第 10493–10495 行的 use_q4 判定与第 213 行 g_st_prefill_q8 默认值,画出"prefill / decode × Q8 / Q4"的四格路由表。

预期输出:你能解释 flags 两个 bit 怎么声明"混合精度文件"、运行期 prefill/decode 为何不同精度,以及"快 vs 准"在路由里的取舍。

收尾

  • 本篇源码点名:vllm_safetensors.c(g_st_prefill_q8 第 213 行、混合精度路由第 10493–10495 行、M4f decode GEMV 第 3849 行起)。
  • 开源仓库:Kestrel-LLM (Gitee)(AGPL-3.0-or-later 或商业许可,二选一)
  • 下篇预告:看表别急着下结论——同一个 bench 连跑五次,gate+up 能从 3.9ms 抖到 6.7ms。下一篇 7-3 讲预热与测量抖动:为什么基准报告"重复 3 次取中位"。
相关文章
|
1天前
|
编解码 应用服务中间件 API
# 0.8MB 跑通 Qwen|第 19-3 篇:视频帧与媒体模块——推理引擎默认不启用的 H.264 独立模块
本系列《0.8MB跑通Qwen》聚焦ARM端零依赖纯C推理引擎,适配Qwen3-VL多模态模型(2B/8B/30B),在RK3588上实测。视频支持分两层:帧序列路径已落地;MP4/H.264解码为独立未完成模块,API清晰、默认不构建、不演示未验证功能,体现严谨工程边界。(239字)
|
1天前
|
缓存 算法 API
0.8MB 跑通 Qwen|第 11-3 篇:推理引擎里 KV 缓存的一生——内存、容量与淘汰
本系列《0.8MB跑通Qwen》聚焦ARM端零依赖纯C推理引擎开发,实测RK3588平台流畅运行Qwen3-VL-2B/8B等多版本。本文详解KV缓存“出生—续用/覆盖—死亡”三段式生命周期,揭示预分配、逻辑覆盖、进程级销毁本质,破除“命中即加速、淘汰即释放”认知误区。(239字)
|
12天前
|
人工智能 测试技术 API
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
Jev是TypeSafe AI推出的“系统一模型”,不生成文本,专做毫秒级结构化决策:Choice(多选)、Score(打分)、Noul(是非概率)。响应快193倍、成本低444倍,适合工单路由、内容审核、测试定级等高频判断场景。
1798 4
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
|
1天前
|
存储 容器
0.8MB 跑通 Qwen|第 17-2 篇:GGUF → VQF——推理引擎的 Q4_0…Q8_K 反量化再量化
本系列《0.8MB跑通Qwen》聚焦ARM零依赖纯C推理引擎,适配Qwen3-VL多版本模型,在RK3588平台实测。本文详解GGUF→VQF的“反量化再量化”路径:将llama.cpp已量化权重(Q4_0/Q8_0等)先还原为F32,再经统一量化与重排固化为VQF格式,确保内核兼容性与可验证性。(239字)
|
1天前
|
编解码 缓存 计算机视觉
0.8MB 跑通 Qwen|第 19-1 篇:ViT 编码——推理引擎里图片是怎么变成视觉 token 的
本系列《0.8MB跑通Qwen》用纯C手写零依赖推理引擎,实现在RK3588(aarch64)上部署Qwen3-VL多模态模型。真机实测:64×64图经24层ViT编码得4个视觉token,耗时仅295.3ms,支持图文理解与视频分析。(239字)
|
1天前
|
存储 缓存 C++
0.8MB 跑通 Qwen|第 9-1 篇:推理引擎的 KV 也量化——q8 KV 把缓存与 decode 带宽压到一半
本系列手搓零依赖纯C推理引擎,仅0.8MB即可在RK3588上跑通Qwen3-VL多模型。本文详解q8 KV量化:将f16 KV压至INT8,按token每头独立定标,缓存与decode带宽降低约48%,兼顾精度与效率,f32仅作调试探针。
|
1天前
|
算法 定位技术 C语言
0.8MB 跑通 Qwen|第 16-3 篇:推理引擎的 tensor 目录与布局重排的落盘顺序
《0.8MB跑通Qwen》系列实录:30天手搓零依赖纯C推理引擎,适配Qwen3-VL多模态模型(2B/8B/30B-A3B),真机跑通RK3588(aarch64)。详解VQFTensor目录结构、64字节对齐落盘、FNV校验及mmap加载机制,含零依赖Python解析器。
|
1天前
|
开发工具 C++ git
0.8MB 跑通 Qwen|第 5-3 篇:推理引擎的参考实现对拍——怎么读懂 rel err 的数量级
本系列《0.8MB跑通Qwen》聚焦ARM端零依赖纯C推理引擎开发,实测适配Qwen3-VL多模型,在RK3588上完成Q8/Q4量化与NEON加速。核心创新在于“两把尺子”误差分析法:内核一致性(1e-7)验证手写代码正确性,量化损失(1e-2)界定精度边界,实现可验证、可调试、可落地的轻量级LLM部署。(239字)
|
1天前
|
JSON 网络协议 前端开发
0.8MB 跑通 Qwen|第 20-3 篇:SSE 流式——推理引擎响应怎么写一半就发给客户端
本系列《0.8MB跑通Qwen》用纯C手搓零依赖推理引擎,适配Qwen3-VL多尺寸模型,在RK3588(aarch64)实测SSE流式响应:首token延迟130ms,后续约50ms/token,支持标准+自定义事件,真正实现端侧“打字机”体验。(239字)
|
1天前
|
安全 索引
0.8MB 跑通 Qwen|第 12-2 篇:推理引擎的磁盘 KV 快照格式——0.47 GB 从哪来
本系列《0.8MB跑通Qwen》聚焦ARM端零依赖纯C推理引擎,实测RK3588上部署Qwen3-VL多模态模型。本文详解0.47GB磁盘KV快照格式:64字节头+token IDs+28层F32原样KV,逐字段对账到字节级,诠释“宁大勿错”的可靠性设计。(239字)

热门文章

最新文章