
llama.cpp 在 Arm CPU 上处理低比特量化模型提示词的速度长期落后于 x86 平台,主要瓶颈在于“平铺 K-量化矩阵乘法”例程缺乏 Arm 原生内核支持。针对 Q3_K、Q2_K 及 IQ 系列等格式,Arm 平台此前只能回退至效率较低的重解压路径。
最新补丁为 llama.cpp v0.9.0 引入了基于 Arm NEON SDOT 指令的内部内核,并在三代 Arm 服务器核心(Neoverse N1/V1/V2)上完成性能验证。测试显示,该优化显著提升了提示词处理速度,而生成速度保持不变。
性能提升显著
在使用 Qwen2.5 1.5B 模型、4 线程及 512-token 提示词的基准测试中,优化后的性能提升如下:
- 最大增益:在 Neoverse N1 上,IQ3_M 格式的处理速度从 11.5 tokens/s 提升至 74.5 tokens/s,增幅达 6.5 倍。
- 普遍提升:IQ3_XS、IQ2_M 等格式在 Neoverse N1 上分别实现 5.9 倍和 4.4 倍的速度提升。
- 无影响格式:已拥有 Arm 内核的 Q4_K_M、Q5_K_M、Q6_K 和 Q8_0 格式性能基本持平,未受负面影响。
值得注意的是,尽管提示词处理速度大幅加快,但文本生成阶段的速度并未改变,因为该阶段不涉及此例程。此外,Arm 平台的绝对性能仍低于 x86 参考水平,具体瓶颈尚待进一步分析。
技术实现细节
该补丁在 ggml/src/ggml-cpu/tiled/ 目录下新增 164 行代码,主要包含两项设计优化:
- 加载时去偏置:内核在加载权重码的同时减去偏置值,利用有符号点积直接在整数运算中完成校正,减少计算步骤。
- 交错提示词侧数据:采用与 VNNI 内核类似的组本地布局,对频带 16 行进行就地交错。每条 lane 的一次 SDOT 指令即可累加四个部分和,无需后续归约,显著提升并行效率。
编译器将在检测到目标 Arm CPU 支持点乘扩展(__aarch64__ 且 __ARM_FEATURE_DOTPROD)时自动启用该例程。
验证与局限性
在 Neoverse N1、V1 和 V2 上,所有 15 个例行测试用例及 88 个随机模糊测试用例均通过验证,且未引入正确性错误。然而,该方案仍存在以下局限:
- 测试环境受限:仅基于 AWS Graviton 服务器测试,未涵盖手机等移动设备。手机端的缓存、内存及散热限制可能导致表现不同。
- 模型与配置单一:仅测试了 Qwen2.5 1.5B 小模型及 4/8 线程配置。预计在线程数超过 16 时,性能增益可能缩小甚至逆转。
- 指令集限制:仅支持 128 位 NEON,未利用 SVE 或 I8MM 等更高级指令集。
- 未覆盖平台:未在 Apple Silicon、Windows on Arm 或小批次(8-32 token)场景下进行测试。
上游状态与致谢
截至 2026 年 11 月 11 日,该补丁尚未提交至 llama.cpp 上游。根据项目贡献规则,AI 生成的代码需由人类贡献者理解并重新撰写 PR 方可合并。相关内核移植工作已见于 unslothai/stable-diffusion.cpp 项目。
本工作由 AI 代理 Nikita(基于 Claude Fable 5.2)在租赁的 AWS Graviton 服务器上完成编写、测试与测量,底层平铺例程由 jbooth 与 bartowski 贡献。