☰
00 · 在 ESP32-P4 上跑通 LLM:从 0.61 到 4.31 tok/s 的 7 倍优化全复盘(系列总览)
2026/9/30 9:27:51 网站建设 项目流程

00 · 在 ESP32-P4 上跑通 LLM:从 0.61 到 4.31 tok/s 的 7 倍优化全复盘(系列总览)

本篇对应源码:仓库根目录 ——README.md·main/kmcu.c·tools/convert_minueza.py·docs/milestones.md

在ESP32-P4(RISC-V)上跑通一个 0.032B(22.8M 参数)Mistral 家族小模型,
并用私有 PIE 向量指令把 decode 加速 7× 的完整复盘。

一、这套文章解决什么问题

这是一份可复现的系列手记,覆盖从「零环境」到「0.032B 模型在 MCU 上 20/20 正确解码」的完整路径,
尤其把过程中踩过的每一个坑和每一个 bug都记录了下来。

适合读者:

  • 想在 ESP32-P4 上跑 LLM 推理的嵌入式工程师;
  • 想了解「MCU 上量化 + 手写 SIMD」全流程的算法/性能工程师;
  • 想复现本项目、或移植到其他 RISC-V MCU 的人。

二、最终成果(先看结果)

里程碑速度说明
M2(标量起点)1.63 s/token(0.61 tok/s)q4 逐元素反量化,正确但慢
M3-1(q4→int8 展开)1.11 s/token(0.90 tok/s)装载期展开
M3-2(行对齐 + -O2)0.511 s/token(1.96 tok/s)修正了 -Og 的隐蔽压制
M3-3(fp16→fp32)0.489 s/token(2.04 tok/s)无损,+4%
M3-4(PIE 定点 GEMV)0.232 s/token(4.31 tok/s)累计 7.0×

正确性:20/20 token 与 PC 的 fp32 NumPy 参考完全一致,int16 激活量化对 argmax 零影响。

硬件:Waveshare ESP32-P4-WIFI6-DEV-KIT(SKU 32054)—— RISC-V 双核 400 MHz、32 MB PSRAM、16 MB NOR Flash。

对拍金标准速览(复现时用来核对)

single-token[1] argmax = 684 (PC 参考 logit=5.350636) 4-token prompt 末位 top1 = 23624 (PC 参考 logit=4.978983) 20-token 贪心序列: 1,450,2217,4996,23624,1199,8752,23624,1199,1199,8752,23624,1199,10436,23624,1199,3065,3161,4865,442

PIE 单算子 bench(板端):

dotprod N=4096 match=1 speedup=20.97x(纯计算) gemv_row diff=0.000000e+00(分块 GEMV 逐位一致)

实跑复现(2026-09-28,ESP32-P4 rev v3.1):dotprod match=1与
gemv_row diff=0.000000e+00可逐位复现;speedup随运行浮动,重跑得20.83x。
同理 M3-4 的 decode 速率在0.226–0.232 s/token(4.33–4.42 tok/s)间浮动,
表中 0.232 s/token 是其中一次读数。

完整 top-8 logits 见 02 篇「完整基准输出」。

三、模型

Felladrin/Minueza-32M-Base(Mistral 家族):

layers=10, dim=312, heads=12, kv_heads=4, head_dim=26, ffn=1092, vocab=32002 参数量 22.81M(`--force-tie` 强制权重共享),Q4_0 量化后 12.58 MB

四、快速开始(最小命令集)

如果你只想最快跑起来,按顺序执行:

# 1) 环境(详见 01-环境搭建与构建.md)subst X:"%USERPROFILE%\.espressif"$env:IDF_TOOLS_PATH ="X:\"$env:IDF_SKIP_CHECK_SUBMODULES ="1".E:\esp-idf\export.ps1$env:PATH ="X:\python_env\idf6.0_py3.12_env\Scripts;"+$env:PATH# 2) 转换模型(详见 02-模型量化与KMCU格式.md)# 在仓库根目录执行;模型与产物统一放 models\ 子目录cd kestrel_mcu python tools\convert_minueza.py--src models\model_dir--out models\model.kmcu--force-tie python tools\ref_forward.py--km models\model.kmcu--ref_out models\ref_out.txt# 3) 构建 + 烧录(构建副本必须在纯 ASCII 路径 C:\kmcu,例如 C:\kmcu)cd C:\kmcu idf.py build idf.py-p COM5 flash# 4) 烧录模型分区(一次性)python-m esptool--chip esp32p4-p COM5-b 921600--before default-reset--after hard-resetwrite-flash0x210000 models\model.kmcu# 5) 监视输出idf.py-p COM5 monitor

五、文章导航

篇内容适合
01-环境搭建与构建ESP-IDF v6.0.2 从零搭建 + 全部环境坑复现第一步必读
02-模型量化与KMCU格式q4_0 量化、行对齐、KMCU v1 二进制格式想改模型/格式的人
03-标量推理内核kmcu.c 的 decode 实现 + TF 卡 + M2想改推理逻辑的人
04-性能优化全历程M3-1→M3-4 每次优化的动机与实测想做性能的人
05-PIE汇编实战手写 xespv 汇编 + 两个致命 bug想用 PIE 的人
06-踩坑速查表所有坑的汇总速查遇到问题先查这里
07-训练流程总览与结论训练侧全地图 + 各技术点闸门判定想知道模型怎么训出来的人
08-经典全量预训练失败归因 + 阶段 0 全量训练突破 ppl 8.73想复现训练的人
09-公理库底座与λ过渡路由SHS-2/3/T + LambdaMoE λ 退火想懂框架特色的人
10-MoE稀疏化实战结构蒸馏失败 → 全量 MoE + ffn_e 扫描想训 MoE 的人
11-量化感知QAT vs PTQ,PTQ +0.9% 足够想做量化的人
12-逐层适配优化逐层量化的公理底座与落地路径想跑大模型的人
13-MoE部署衔接缺口convert + 内核的 MoE 支持缺口想打通端到端的人
14-架构寻路与PLE12 个优化判否全历程 → 发现并验证 PLE 正解想做「更大模型」的人
15-三值量化变种全模型三值判否 → 局部三值(PLE table)成立 → ReLU² 判否想做极致压缩的人
16-PLE落地验证dim 312 真实配置下 PLE 成立 + 三值几乎无损想落地 PLE 的人
17-MoE框架下的PLE实现MoEFFN 实现 + MoE 与 PLE 正交共存 + 完整配方验证想做完整配方的人
18-对标PFor与esp32-ai与 PFor / esp32-ai 的技术级横向对比 + 借鉴与独有差异想外部校准配方的人
19-PLE部署落地PLE 三值查表 + tied head 上板:DT_TERNARY 格式 + 内核 + 堆溢出 bug想打通 PLE 部署的人
20-PLE为什么不加速PLE 收益在容量不在速度:读量归因 + tied 只省存储不省读量想知道速度真相的人
21-PFor选择速度我们选择质量速度 vs 质量零和博弈:PFor 三值换速度、我们 q4 换质量想懂设计取舍的人
22-正式训练与端到端闭环FineWeb-Edu 正式训练(ppl 37.13)+ 部署对拍 20/20想复现完整配方的人
23-规模线与PLE-table本质更大模型「大」在哪 + PLE table 到底是不是知识库想懂规模线本质的人
24-决策头vs生成头Jev/Laya 启示:决策任务用「决策头」而非「生成头」,读量省 16000×想做 MCU 决策的人
25-双头融合-该判断时判断该输出时输出决策头+生成头融合框架:三种形态 + 元决策 + agent 循环想建统一模型的人
26-观察回接-Agent循环观察回接核心机制:λ 框架 + 截断观察回接 + 增量 KV 位级一致性想做 MCU agent 循环的人
27-map直挂缓存判否mmap 直挂 flash 带宽基准:14MB/s 是 PSRAM 1/7.6,大模型直挂判否想省 PSRAM 装更大模型的人

六、关键结论(提炼)

  1. PIE 是纯定点 SIMD,没有 fp32 向量指令(乐鑫源码铁证)。要加速int8 权重 × fp32 激活的 GEMV,
    唯一路径是激活定点化(w8a16)。
  2. 实测胜于推论:纯计算加速 21×,但接入后被 PSRAM 带宽墙(~84–106 MB/s)压到2.11×。
  3. -Og是隐形杀手:ESP-IDF 默认 debug 优化级会系统性压低性能读数,M1/M2/M3-1 的数据都被它污染过。
  4. 两个 PIE 硬约束:标量操作数不能用 t0-t2 寄存器、向量加载需 16 字节对齐——不满足会得到「随机数据对拍正确、真实数据全错」的诡异现象。

七、项目文件索引

kestrel-llm-mcu/ # https://gitee.com/pei-xiaoguang/kestrel-llm-mcu ├── main/ 固件 │ ├── main.c # 入口:SHS 自检 + PSRAM/TF 探针 + 模型加载 + decode + PIE bench + 三模式 │ ├── kmcu.c / kmcu.h # KMCU 权重读取 + 标量/PIE Transformer decode + 决策头 + agent 循环 │ ├── pie_dotprod.S # PIE(xespv)定点 GEMV 汇编 │ └── CMakeLists.txt ├── tools/ 宿主侧工具链(详见 tools/README.md) │ ├── mistral_ple.py # 架构唯一权威源(MistralPLE) │ ├── convert_minueza.py# HF safetensors → KMCU 量化权重 │ ├── ref_forward.py # PC 端 fp32 NumPy 参考(唯一对拍基准) │ ├── train_moe_ple.py # 训练 │ ├── watch_boot.py # 复位 + boot 日志监视 │ ├── upload_uart.py # UART 上传(experimental) │ └── legacy/ # 归档的历史研究脚本(含本文系列早期用到的 train_moe*.py 等) ├── docs/ 设计文档 + 开发日志(中英双版) ├── host_verify.c # PC 侧对拍程序(编译同一份 kmcu.c) ├── partitions.csv # Flash 布局(app 2 MB / model 13.87 MB) ├── sdkconfig.defaults # 关键配置(-O2、Newlib、PSRAM hex、关 WDT) └── LICENSE / NOTICE # Apache-2.0 + 第三方声明

注:GitHupSRC/(vLLM-Kestrel 引擎)与kestrel_mcu/是两个独立项目,
本系列只讲kestrel_mcu/这一条独立 determinism line,不涉及引擎源码。


对应源码(全系列总表)

每篇文末都有一节「对应源码」,给出该篇的符号级映射(文件 + 函数/宏 + 它支撑文中的哪部分结论)。
下表是系列导航级的速查:想直接读代码,从这里进。

篇主要源码
00 总览与阅读指南README.md·docs/milestones.md
01 环境搭建与构建sdkconfig.defaults·partitions.csv·main/main.c·CMakeLists.txt
02 模型量化与 KMCU 格式tools/convert_minueza.py·main/kmcu.h·tools/ref_forward.py
03 标量推理内核main/kmcu.c·main/kmcu.h·host_verify.c
04 性能优化全历程main/main.c·main/kmcu.c·main/pie_dotprod.S
05 PIE 汇编实战main/pie_dotprod.S·main/main.c
06 踩坑速查表main/kmcu.c·main/main.c·sdkconfig.defaults
07 训练流程总览与结论tools/mistral_ple.py·tools/train_moe_ple.py·docs/lambda_transition_framework.md
08 经典全量预训练tools/legacy/full_finetune.py·tools/mistral_ple.py
09 公理库底座与 λ 过渡路由docs/lambda_transition_framework.md·tools/legacy/train_moe.py·tools/legacy/train_lambda.py
10 MoE 稀疏化实战tools/legacy/train_moe.py·tools/legacy/train_lambda.py·docs/moe_framework.md
11 量化感知tools/legacy/train_moe_qat.py·tools/legacy/verify_q2.py·tools/convert_minueza.py
12 逐层适配优化docs/layerwise_adaptation.md·tools/legacy/train_moe_qat.py
13 MoE 部署衔接缺口main/kmcu.c·main/kmcu.h·docs/moe_framework.md
14 架构寻路与 PLEtools/mistral_ple.py·tools/legacy/dense_baseline.py
15 三值量化变种tools/mistral_ple.py·tools/convert_minueza.py·main/kmcu.c
16 PLE 落地验证tools/mistral_ple.py·tools/train_moe_ple.py
17 MoE 框架下的 PLE 实现tools/mistral_ple.py·tools/train_moe_ple.py·docs/moe_framework.md
18 对标 PFor 与 esp32-aiREADME.md·docs/milestones.md
19 PLE 部署落地tools/convert_minueza.py·main/kmcu.c·host_verify.c
20 PLE 为什么不加速main/kmcu.c·docs/milestones.md
21 PFor 选择速度我们选择质量docs/milestones.md·README.md
22 正式训练与端到端闭环tools/train_moe_ple.py·tools/convert_minueza.py·tools/ref_forward.py·host_verify.c
23 规模线与 PLE-table 本质tools/mistral_ple.py·docs/milestones.md
24 决策头 vs 生成头main/kmcu.c·main/main.c·docs/agent_loop_router.md
25 双头融合main/main.c·main/kmcu.c·docs/agent_loop_router.md
26 观察回接-Agent 循环main/kmcu.c·main/kmcu.h·docs/agent_loop_router.md
27 map 直挂缓存判否main/main.c·main/kmcu.h·docs/milestones.md

注:09 与 15 篇引用的axiom_registry.json为内部文件,未随本仓库发布。


对应源码

文件关键符号 / 位置支撑本文哪部分
README.mdHighlights (measured)、Repository layout§二 最终成果、§四 快速开始
docs/milestones.mdM1 / M2 / M3-x 全部小节§二 M2→M3-4 各档实测数据
main/main.cshs_selftest()、probe_psram()、probe_sdcard()、model_test()§四 第 3/4/5 步的板端自检与模型加载
tools/convert_minueza.pySRC_DIR/OUT_PATH(KMCU_SRC/KMCU_OUT环境变量)§四 第 2 步转换命令

仓库:https://gitee.com/pei-xiaoguang/kestrel-llm-mcu

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询