1. LLaMA Now Goes Faster on CPUs (justine.lol)
文章标题:LLaMA Now Goes Faster on CPUs
核心内容概述
作者为 llamafile 项目(基于 llama.cpp 的跨平台单文件封装)编写了84个新的矩阵乘法内核,显著提升了在CPU上处理提示词(Prompt)和图像的速度。与 llama.cpp 相比,在使用F16和Q8_0权重时,提示词评估(prompt eval)速度在CPU上提升了30%到500%。性能提升在ARMv8.2+(如Raspberry Pi 5)、Intel Alderlake和AVX512(如Zen 4)等平台上尤为明显。新内核在L2缓存内的矩阵运算中速度是MKL的2倍,但目前在超过1000个标记的提示词上效果最佳。
详细技术内容
1. 性能提升数据
- 企业级硬件 (Intel i9-9900):对于Mistral 7B模型(q8_0权重),
llamafile-0.7的提示词处理速度是llama.cpp的1.45倍,是旧版llamafile的2倍。 - 爱好者硬件 (Raspberry Pi 5):使用ARMv8.2的fp16指令集,TinyLlama 1.1B模型(f16权重)的提示词速度是
llama.cpp的2.2倍。 - 游戏硬件 (Intel i9-14900K Alderlake):Mistral 7B模型(q8_0权重)提示词速度比
llama.cpp提升58%;TinyLlama 1.1B(f16权重)提升3.5倍。 - 专业硬件 (AMD Threadripper 7995WX):支持AVX512,新增bf16支持。Mistral 7B(bf16权重)提示词速度是
llama.cpp的2.8倍。
2. 优化原理
- 聚焦关键操作:性能提升源于针对
GGML_OP_MUL_MAT(矩阵乘法)操作的深度优化,该操作消耗了95%的推理时间。 - 向量化与循环展开:核心优化技术是向量化的外积循环展开。通过同时计算输出矩阵的多个元素(如3x4的块),共享加载的输入向量(如
a0),最大化利用CPU的指令级并行和缓存,减少内存访问次数。 - 轻量级线程模型:为了适配
llama.cpp的旋转屏障(spinlock)线程模型,实现了自己的线程分块内核框架,避免了传统BLAS库的线程管理开销,使计算能无缝集成到现有的多线程流程中。
3. 关键技术细节
- 处理不同矩阵大小:通过递归的“分块打包”(
mnpack)策略,将矩阵划分为可被特定大小内核(如3x4)处理的块,处理剩余部分。 - 硬件指令集利用:针对不同架构使用最优指令,如在x86上使用AVX2/AVX512的FMA指令,在ARM上使用fp16和dotprod指令。
- 精度权衡:在ARMv8.2+上使用fp16计算可能引入舍入误差,但速度更快;Q8_0使用dotprod指令则精度稍好。作者强调应让模型以声称的位宽运行。
4. 实际应用示例
- 垃圾邮件过滤:展示了在Raspberry Pi 5上,使用TinyLlama模型和
--grammar参数强制单标记输出,在3秒内完成邮件分类。 - 提示词速度的重要性:强调在诸如文本摘要、LLaVA图像处理等需要处理长上下文的场景中,提示词评估速度比标记生成速度更关键。
5. 项目背景与贡献
llamafile是与Mozilla合作的项目,旨在将llama.cpp封装为单一跨平台二进制文件。- 作者已将优化后的矩阵乘法内核提交至
llama.cpp上游(PR #6414, #6412),并将许可证改为MIT,以促进更广泛的开源社区采用。 - 工作重点是通过改进核心技术,为用户提供最佳的本地LLM体验,特别是服务于没有高端GPU的用户。
结论
通过专门优化的矩阵乘法内核和适配的线程模型,llamafile 在多种CPU硬件上实现了显著的提示词处理速度提升,使得在CPU上运行大型语言模型更加高效和实用。优化效果在特定模型大小(如7B)和权重格式(f16, q8_0)下表现最佳,降低了本地LLM部署对量化技术的依赖。