速度翻倍的秘密:PicoLM融合反量化+点积的矩阵乘优化
【免费下载链接】picolmRun a 1-billion parameter LLM on a $10 board with 256MB RAM项目地址: https://gitcode.com/gh_mirrors/pi/picolm
PicoLM 是一个纯 C 语言编写的超轻量 LLM 推理引擎,能在 256MB 内存的 10 美元开发板上运行 10 亿参数的大语言模型。本文带你看懂它最核心的提速技巧——融合反量化 + 点积的矩阵乘优化,理解这个小改动如何让推理速度直接翻倍。
🐢 瓶颈在哪:量化权重让矩阵乘变慢
在 LLM 推理中,每个 token 的生成都要经过 22 层 Transformer,而每层最耗时的操作就是矩阵乘(matmul):把 2048 维的输入向量乘上巨大的量化权重矩阵。
PicoLM 的权重以 Q4_K 格式存储在磁盘上(通过 mmap 按需读入)。在 picolm/quant.h 中可以看到 Q4_K 的数据结构:每 256 个权重只占 144 字节,还带有两级缩放因子(d、dmin)和 6-bit 子块 scale。
最初的朴素实现是两遍式的:
第一遍:把整行量化权重反量化成 float,写入临时缓冲区 第二遍:用临时缓冲区与输入向量做点积问题在于:反量化出来的 float 要先写回内存,点积时再读回来。在内存带宽极其紧张的 10 美元小板上,这一来一回的内存流量就是速度的杀手。
⚡ 融合优化:点积在反量化的同时完成
PicoLM 的解法是融合(Fusion):不生成任何中间缓冲区,在解出每个量化值的同时就完成乘累加。核心实现是 picolm/quant.c 中的vec_dot_q4_K_f32()函数。
它的巧思在于利用 Q4_K 的数学结构:
- 按子块分组累加:每个子块的量化值都要乘以同一个 scale,所以先把
nibble × x的乘积和x的单独求和分别累加; - 缩放只做一次:每个子块结束才做一次
scale × 乘积和 - min × x和,避免逐元素乘缩放因子; - 零中间内存:反量化后的 float 值只存在于寄存器里,从不落盘到缓冲区。
// 伪代码思路:每 32 个元素累加,子块结束统一缩放 sum_qx += (float)(q[l] & 0xF) * xp[l]; // 低 4-bit × 输入 sum_x += xp[l]; // 输入单独求和(给 min 偏移用) sumf += d * scale * sum_qx - dmin * mn * sum_x; // 每个子块只缩放一次这一招把矩阵乘的内存流量砍掉约一半,实测效果是速度从 1.6 tok/s 提升到 3.0 tok/s——整整翻倍(详见 BLOG.md 的 "Optimization 1" 章节)。
🧵 组合拳:多线程 + SIMD 再提速
融合点积只是第一块拼图,PicoLM 把它和另外两个优化无缝拼接:
① 多线程矩阵乘
tensor.c 中matmul_worker()把输出行按区间切给多个线程,每个线程独立调用融合点积处理自己的权重行——权重行连续访问,对缓存预取非常友好。入口 matmul() 自动做行数均分,主线程也参与计算(worker 0)避免空转。
② NEON / SSE2 三级 SIMD
每个点积内核都提供三个版本(见 quant.c 注释):
| 层级 | 适用平台 | 特点 |
|---|---|---|
| NEON | Raspberry Pi 3/4/5 (ARM) | 128-bit 向量,一次处理 4 个 float |
| SSE2 | x86 开发机 | 自动检测 Intel/AMD |
| 标量回退 | 其他 | 保证任何平台都能跑 |
NEON 路径下,8 个量化字节一次载入,通过vand_u8/vshr_n_u8拆出高低 4-bit nibble,再vmovl逐级拓宽成 float 做 FMA 融合乘累加——整条流水线全程无临时内存写入。
📊 效果一览
PicoLM 的 README.md 记录了完整的优化阶梯,融合点积是其中关键一步:
| 优化项 | 效果 |
|---|---|
| 朴素标量推理(基线) | 1.6 tok/s |
| + 融合反量化+点积 | ≈2x,达到 3.0 tok/s |
| + 多线程 matmul(4 核) | 9.4 tok/s |
| + NEON/SSE2 SIMD + 其余优化 | x86 13.5 tok/s,Pi 4 可达 30+ tok/s |
配合 FP16 KV 缓存、预计算 RoPE 表、Flash Attention 等 9 项优化,整个引擎用约 2500 行 C 代码就跑出了嵌入式设备的极限速度。
📁 关键源码导读
想动手研究的同学,按这个路径看效率最高:
- 数据格式:picolm/quant.h —— Q4_K 块结构与 SIMD 探测宏
- 融合点积核心:picolm/quant.c —— NEON / 标量两条路径
- 类型分发:picolm/quant.c ——
vec_dot()统一入口 - 矩阵乘调度:picolm/tensor.c —— 行切分与线程创建
- 接口声明:picolm/tensor.h 与 picolm/quant.h
- 完整优化故事:BLOG.md —— 从 1.6 到 30+ tok/s 的七步优化实录
🚀 快速上手
# 克隆仓库 git clone https://gitcode.com/gh_mirrors/pi/picolm cd picolm/picolm # 自动检测 CPU(x86 开 SSE2/AVX,ARM 开 NEON) make native # 树莓派请用 make pi # 下载模型并运行 make model ./picolm model.gguf -p "The meaning of life is" -n 100 -j 4也可以用 install.sh 一行命令完成安装。
小结
融合反量化 + 点积的思想其实很简单:能不在内存里存的东西,就不要存。在内存带宽就是命的小硬件上,省掉的一次写+读就是翻倍的底气。这也是 PicoLM 能装进 80KB 二进制、45MB 内存还保持飞快推理的秘诀之一——嵌入式优化的本质,往往不是更复杂的算法,而是更少的内存搬运。
【免费下载链接】picolmRun a 1-billion parameter LLM on a $10 board with 256MB RAM项目地址: https://gitcode.com/gh_mirrors/pi/picolm
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考