📖 第1课:AI 推理是怎么在 FPGA 上跑起来的?
从零理解 AI 模型推理、FPGA 硬件加速、HLS 设计——用生活比喻讲清楚。
理解"AI推理"和"AI训练"的区别、FPGA 为什么比 CPU 快、HLS 怎么把 C++ 变成电路。
一、AI 推理 vs AI 训练 —— 做饭 vs 看菜谱
训练和推理的区别
训练就像大厨花几个月研究菜谱(用海量数据调整模型参数),只需要做一次。推理就像照着菜谱炒菜(用户输入→模型计算→输出结果),要做无数次。MiniCpm5 和 Qwen2.5 做的都是推理加速——让"炒菜"这一步更快更省电。
二、语言模型的"最后一关":lm_head 输出头
语言模型(比如 MiniCPM5-1B)本质上是一个"下一个词预测器"——给它前面的文字,它猜下一个词。这个"猜"的过程就是把它内部的 hidden state(一个 1536 维的向量)乘以一个巨大的权重矩阵(1536×130560),算出一个分数表,分数最高的就是最可能的词。
从 Hidden State 到 Token
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
三种计算平台对比
| 平台 | 速度 | 功耗 | 灵活性 | 适合什么 |
|---|---|---|---|---|
| CPU | 慢 | 中 | 最高 | 通用计算 |
| GPU | 快 | 高(200W+) | 中 | 训练/大batch推理 |
| FPGA ⭐ | 较快 | 低(<10W) | 高(可重配) | 低功耗边缘推理 |
| ASIC | 最快 | 最低 | 无(流片后不可改) | 量产芯片 |
FPGA 的甜蜜点:低功耗 + 可重配。如果算法变了,重新烧录即可——不像 ASIC 流片后就不能改了。对于还在快速迭代的 AI 算法,FPGA 是最好的验证平台。
四、HLS(高层次综合)—— 用 C++ 写硬件
传统上,写 FPGA 硬件要用 Verilog/VHDL(和 rv_control 一样)。但 HLS 允许你用 C++ 写算法,工具自动帮你翻译成电路。
HLS 四阶段流水线
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 | 延迟 | FF | LUT |
|---|---|---|---|---|
| Direct BRAM | 4 | 207,873 | 1,322 | 1,342 |
| Preload Cache ⭐ | 1 | 59,781 | 15,431 | 12,393 |
Direct BRAM直接读隐藏层数据,但 32 个并行通道同时读一块 BRAM 会冲突(就像 32 个人同时想从一扇门出去),所以每 4 个周期才能完成一次操作(II=4)。
Preload Cache先把隐藏层数据预加载到本地高速缓存(用 FF 实现),32 个通道各读各的,不冲突。代价是 FF 多了 11.7 倍(15,431 vs 1,322),但 VU19P FPGA 有大量 FF 资源,完全可以承受。
用更多硬件资源(FF/LUT/DSP)换取更高的吞吐量(II=1)。在资源充足的 VU19P 上,"空间换时间"是正确的策略。