桃子桃子快讯
返回首页
开源

开源项目实现 GGUF 模型在 Axera NPU 上直接推理

开发者为 llama.cpp 编写 Axera AX8850 NPU 后端,支持 Qwen3-0.6B 从 GGUF 直…

2026.08.26 · 周三4 分钟阅读

一名开发者近日在 GitHub 上发布了 llama.cpp 的自定义后端 ggml-axcl,首次实现了将 GGUF 格式的 Qwen3-0.6B 模型直接运行在搭载于树莓派 5 的 Axera AX8850 NPU 加速卡(24 TOPS INT8、8 GB LPDDR4x)上。整个流程仅需一份 GGUF 模型文件,权重在加载时由 NPU 引擎流式读取,Q8_0 与 Q4_K_M 两种量化均可走同一代码路径。

性能现状与差距分析

当前实测解码速度约为 1.3–2.7 tokens/s,而厂商基于烤入权重与封闭运行时的参考方案可达 13.5–16.9 tokens/s。作者对此进行了详细的架构归因:

  • 每个生成 token 需要约 120–140 次 NPU 引擎调用(7 次矩阵乘 × 28 层 + 词表头);
  • 每次调用中,CPU 端负责 RMSNorm、RoPE、softmax、masking、加法、GLU 等粘合操作,NPU 实际执行仅约 0.6 ms,但被约 2–3 ms 的 host 调度与 PCIe DMA 开销包裹;
  • 由于 llama.cpp 调度器将计算图拆分为按算子分片,NPU 约有 80% 的时间处于空闲等待状态,CMM 占用 7 GB 时 NPU 利用率仅约 21%。

厂商方案将整层融合为一次 NPU 调用(norm + qkv + rope + 带片上 KV 缓存的注意力 + FFN + GLU),每 token 仅 28 次调用且无 host 往返,单层耗时约 1.5 ms,这正是 5–10 倍性能差距的来源。

权重路径已打通

项目核心突破在于 Pulsar2 的 AxQuantizedMatMul 自定义算子可直接接受 int8 权重作为运行时张量输入,因此 GGUF 权重只需在加载时量化一次、上传并按调用绑定,相比 f32 路径减少 4 倍传输量,无需额外转换步骤。

测试覆盖与已知问题

截至 2026-08-26 的端到端测试中,13/14 自动化用例通过,覆盖 1–3000 token 提示、unicode、emoji、shell 元字符、2000 字符长词、单字符、长生成等场景。期间修复了 llama-simple 中 n_batch=0 断言与零 token 批次的 BOS 回退崩溃,并验证了 SIGINT 干净退出、5 次连跑无泄漏、2 路并发正确性。

设备驻留 chain 模式(GGML_AXCL_CHAIN=1)已在 180 token 提示下验证一致;跨分片 QKV 融合虽实现并通过逐位比对,但默认关闭,因为调度器在写回前会插入 q_norm/rope 的 CPU 分片从而破坏 KV 缓存。

后续路线图

要逼近厂商性能,需完成以下工作:

  • 全面启用 chain 模式,将逐元素运算搬上 NPU;
  • 矩阵乘设备流水化,通过 g_chain_x_override 从设备驻留缓冲绑定 X,消除每次调用的 H2D 传输;
  • 注意力引擎覆盖全部上下文长度,修复当前要求 seq > 128 的激活门控;
  • 整层引擎:权重布局已完全逆向(int4 半字节对 + 完整位置表,存于 gemm/layer_layout_v3.pkl),剩余 scale 表映射与基于 axclrtEngineLoadFromMem 的权重补丁加载器待完成。

构建与运行

在树莓派上执行 cmake 构建并启用 GGML_AXCL=ON 即可获得 llama-simple 可执行文件,加载 ~/models/qwen3-q8.gguf 即可生成。引擎需在 x86_64 开发机上用 Pulsar2 从 ONNX 源编译后部署到 Pi 的 /usr/local/share/ggml-axcl/。项目同时提供了 GGML_AXCL_ASYNC、GGML_AXCL_WPOOL_MB、GGML_AXCL_DEBUG 等环境变量用于异步执行、权重池调节与诊断日志。

信源