📖 第1课:AI 推理是怎么在 FPGA 上跑起来的?

从零理解 AI 模型推理、FPGA 硬件加速、HLS 设计——用生活比喻讲清楚。

🎯 本课目标

理解"AI推理"和"AI训练"的区别、FPGA 为什么比 CPU 快、HLS 怎么把 C++ 变成电路。

一、AI 推理 vs AI 训练 —— 做饭 vs 看菜谱

训练和推理的区别

flowchart LR subgraph TRAIN["🔧 训练 (做一次)"] T1[海量数据] --> T2[调整参数] T2 --> T3[训好的模型] end subgraph INFER["⚡ 推理 (做无数次)"] I1[用户输入] --> I2[加载训好的模型] I2 --> I3[算出结果] end TRAIN -->|产出| INFER style TRAIN fill:#e66767,color:#fff style INFER fill:#199e70,color:#fff

训练就像大厨花几个月研究菜谱(用海量数据调整模型参数),只需要做一次。推理就像照着菜谱炒菜(用户输入→模型计算→输出结果),要做无数次。MiniCpm5 和 Qwen2.5 做的都是推理加速——让"炒菜"这一步更快更省电。

二、语言模型的"最后一关":lm_head 输出头

语言模型(比如 MiniCPM5-1B)本质上是一个"下一个词预测器"——给它前面的文字,它猜下一个词。这个"猜"的过程就是把它内部的 hidden state(一个 1536 维的向量)乘以一个巨大的权重矩阵(1536×130560),算出一个分数表,分数最高的就是最可能的词。

从 Hidden State 到 Token

flowchart LR A["🔢 hidden state
1536维向量
(模型对当前文本的理解)"] -->|"矩阵乘法
hidden × weight"| B["📊 logit 分数表
130560个分数
(每个词一个分数)"] B -->|"argmax
选最大的"| C["📝 token_id
得分最高的词"] C -->|"detokenize"| D["💬 输出的文字"] style A fill:#3987e5,color:#fff style B fill:#c98500,color:#000 style D fill:#199e70,color:#fff

这个"矩阵乘法"就是整个 MiniCpm5 项目要加速的核心——lm_head(语言模型输出头)。它的计算量:1536×130560≈2亿次乘法——每个 token 生成都要算一遍。

三、为什么用 FPGA?—— CPU vs FPGA vs ASIC

三种计算平台对比

pie title 计算平台选择 "CPU (通用但慢)" : 30 "GPU (快但贵费电)" : 30 "FPGA (可重配/省电)" : 20 "ASIC (最快/不可改)" : 20
平台速度功耗灵活性适合什么
CPU最高通用计算
GPU高(200W+)训练/大batch推理
FPGA ⭐较快低(<10W)高(可重配)低功耗边缘推理
ASIC最快最低无(流片后不可改)量产芯片

FPGA 的甜蜜点:低功耗 + 可重配。如果算法变了,重新烧录即可——不像 ASIC 流片后就不能改了。对于还在快速迭代的 AI 算法,FPGA 是最好的验证平台。

四、HLS(高层次综合)—— 用 C++ 写硬件

传统上,写 FPGA 硬件要用 Verilog/VHDL(和 rv_control 一样)。但 HLS 允许你用 C++ 写算法,工具自动帮你翻译成电路。

HLS 四阶段流水线

flowchart LR CPP["📝 C++ 算法
lm_head_real24_topk"] -->|"CSim"| CSIM["✅ C仿真
纯软件验证算法正确
token=10, logit=-5483"] CSIM -->|"CSynth"| CSYNTH["✅ C综合
C++→Verilog RTL
估计: DSP=64, FF=15431"] CSYNTH -->|"Cosim"| COSIM["✅ C/RTL协同仿真
RTL周期精确验证
延迟=59781 cycles"] COSIM -->|"IP Drop"| IP["📦 IP包
可集成到Vivado工程"] style CSIM fill:#199e70,color:#fff style CSYNTH fill:#c98500,color:#000 style COSIM fill:#e66767,color:#fff style IP fill:#0ca30c,color:#fff

HLS 的核心优势:快速探索不同的并行度。在 C++ 里加一行 `#pragma HLS PIPELINE II=1` 就能让循环每个周期处理一个元素,不需要重写 Verilog。MiniCpm5 用 HLS 把 1536×1024 的矩阵乘法映射到 32 个并行乘法器上,59,781 个周期算完。

五、Preload Cache —— 用空间换时间

HLS 综合工具给出了两个版本的资源对比:

版本II延迟FFLUT
Direct BRAM4207,8731,3221,342
Preload Cache ⭐159,78115,43112,393

Direct BRAM直接读隐藏层数据,但 32 个并行通道同时读一块 BRAM 会冲突(就像 32 个人同时想从一扇门出去),所以每 4 个周期才能完成一次操作(II=4)。

Preload Cache先把隐藏层数据预加载到本地高速缓存(用 FF 实现),32 个通道各读各的,不冲突。代价是 FF 多了 11.7 倍(15,431 vs 1,322),但 VU19P FPGA 有大量 FF 资源,完全可以承受。

💡 这就是 FPGA 设计的核心 trade-off

用更多硬件资源(FF/LUT/DSP)换取更高的吞吐量(II=1)。在资源充足的 VU19P 上,"空间换时间"是正确的策略。