开发者逆向 Axera NPU 引擎格式,llama.cpp 直跑 GGUF 实现 1.5 倍加速
开发者破解 AX8850 NPU 引擎的半字节平面布局,让 llama.cpp 无需模型转换即可加载 GGUF,在树莓派…
一位独立开发者近日在 Reddit r/LocalLLaMA 板块发布了一项针对 Axera AX8850 NPU 的逆向工程成果:通过破解其编译引擎格式(.axmodel)的内部布局,他让 llama.cpp 能够在无需模型转换的前提下直接加载 GGUF 权重文件,并在搭载该 NPU 的 Raspberry Pi 5 上跑出比厂商自带运行时更高的速度。
背景:被卡住的 GGUF 直跑路径
开发者使用 M5Stack LLM-8850 加速卡(基于 Axera AX8850,标称 24 TOPS,配备 8GB LPDDR4x 内存)配合 Raspberry Pi 5 作为 llama.cpp 的推理后端。此前的问题是:厂商的工具链要求所有模型必须经过其编译器转换,而其封闭运行时只能达到 13.5–14.5 t/s。开发者的目标是实现「GGUF 进去、token 出来」的原生工作流。
核心突破:破解引擎格式并实现热加载
-
逆向权重布局:NPU 编译产物中的 npu_params 区域将 int8 权重以两组半字节(nibble)平面存储——粗粒度字节携带元素对的两个高 4 位,细粒度字节(偏移 18 个位置)携带低 4 位。为还原完整布局,开发者构建了约 10 个「标记」checkpoint,将每个权重的自身坐标编码进去,再用厂商工具链编译并 diff 输出,最终得到每层 7 个矩阵的完整排布及 scale 表。
-
零转换 GGUF 补丁加载:在运行时将 GGUF 反量化后再量化到引擎自身尺度,只写入真正变化的字节,跳过模型编译步骤。输出与同一 GGUF 的 CPU 推理结果达成 96% token 一致性。
-
修复被误判的批预填充路径:发现厂商的预填充 shape-groups 实际上可用,bug 来自示例代码中输出缓冲区的绑定方式。修复后达到 716 t/s 的预填充速率,输出与此前逐字节一致。
实测性能与带宽瓶颈分析
在 Pi 5 上的贪婪解码单流测试中(int4 引擎):
- 2k 上下文:24.5 t/s 解码;1k 上下文编译版可达 29.9 t/s
- 裁剪词表头后:26.8 t/s
- 提示处理速度:716 t/s
- Pi CPU 几乎空闲,推理全部由加速卡承担
进一步分析揭示了一个被忽视的硬件事实:在 batch-1 解码场景下,AX8850 实际上是内存带宽受限——有效流式带宽约 25 GB/s,达到 LPDDR4x 峰值的 73%;MAC 利用率仅约 1%。开发者总结出经验公式:「解码速度 = 每 token 字节数 × 每权重 pass token 数」,该框架成功预测了实验中获得的所有加速收益(int4 量化 1.5×、批预填充 39×、词表裁剪 +10%)。
开源资源与可复现性
所有成果均以开源形式发布:
- 项目仓库(含快速上手、性能分析、布局破解工具集、片上测试框架):github.com/woolcoxm/LLMTest
- llama.cpp 分支后端(单文件约 4500 行):github.com/woolcoxm/llama.cpp
- 24 t/s 实测运行截图:仓库 docs/demo.png
复现路径只需在任意装有 AXCL 驱动的 aarch64 主机上使用 -DGGML_AXCL=ON 编译 llama.cpp,指向引擎集并喂入 GGUF 即可完成完整流程。
