如何使用FPGA实现深度学习完整教程与技巧详解
针对全连接层(fc1、fc2)这一推理瓶颈,采用循环数据并行化优化,并通过层间平衡使各层执行周期均等。最终版本从基线20 81毫秒降至0 0498毫秒,加速417 87倍,资源消耗中DSP仅从20增至63。实验基于MNIST数据集,真实场景需结合量化和剪枝等技术。
在本系列教程中,我们将逐步探索如何利用FPGA实现深度学习推理。本文是第九篇,前几篇文章已详细讲解了任务并行度、循环并行度以及数据并行度的提取与优化策略。本文将重点展示全连接层的循环数据并行化优化,并给出最终版本的整体性能对比与资源使用分析,让您直观感受每次优化带来的加速效果。
全连接层优化:突破性能瓶颈
在上一篇文章《从FPGA说起的深度学习(八)-数据并行性》中,我们发现全连接层(fc1、fc2)是整个推理流程的主要瓶颈。为此,我们实现了针对全连接层的优化版本。具体代码请查看代码存储库中的 linear.h 文件(文末提供链接)。全连接层本质上是向量与矩阵的乘积,与卷积层不同,它无法在两个通道上实现并行化,但基本沿用了与卷积层相似的优化思路(例如循环展开、数据分块)。
根据第6篇文章的结论,当各任务的处理时间趋于一致时,任务并行性才能发挥最大效能。下表展示了最终版本每个层的并行化程度和执行周期数,经过参数调整后的 conv1、conv2、fc1、fc2 的执行周期非常均衡,原本处理耗时较低的 fc2 现在也与其它内核基本持平。
| 层 | 并行度(输出通道) | 平行度(x方向) | 执行周期数 | 执行时间(us) |
|---|---|---|---|---|
| conv1 | 4 | 4 | 12741 | 42.466 |
| conv2 | 4 | 8 | 12937 | 43.119 |
| fc1 | 4 | – | 12721 | 43.399 |
| fc2 | 1 | – | 383 | 1.277 |
各层的并行度与处理性能详情
小提示: 当某个层的执行时间远低于其他层时,可以考虑适当降低其并行度以节省硬件资源,或者将释放的资源分配给更耗时的层,实现整体负载均衡,提升系统吞吐量。
整体加速效果:从基线到最终版
从第3篇到第8篇,我们依次应用了任务并行化、循环并行化、数据并行化到推理内核。下表清晰展示了每一步优化带来的性能提升幅度。
| 名称 | 执行时间(毫秒/图像) | 比上一版提速倍数 | 相对于基线的提升倍数 |
|---|---|---|---|
| 基线 | 20.81 | 1.00 | 1.00 |
| 任务并行化 | 12.65 | 1.65 | 1.65 |
| 通过本地缓冲区减少外部存储器访问 | 1.61 | 7.86 | 12.93 |
| 循环并行化(仅限卷积层) | 0.61 | 2.64 | 34.11 |
| 数据并行化 4×4(仅卷积层) | 0.336 | 1.81 | 61.93 |
| 最终版本 | 0.0498 | 6.75 | 417.87 |
整体加速效果汇总
可以看到,从基线到最终版本,执行时间从 20.81 ms 锐减到 0.0498 ms,加速了 417.87 倍!其中效果最显著的两个优化点分别是:
- 使用本地缓冲区减少外部存储器访问(加速比 7.86 倍)
- 最终版本(加速全连接层 + 层间平衡)(加速比 6.75 倍)
资源使用分析:性能与成本的权衡
除了性能,资源消耗也是FPGA设计中的关键考量因素。以下是各优化版本的资源利用情况(BRAM、DSP、FF、LUT)。
| 名称 | BRAM_18K | DSP48E | FF | LUT |
|---|---|---|---|---|
| 基线 | 49 | 20 | 13592 | 15600 |
| 任务并行化 | 61 | 20 | 13785 | 15955 |
| 通过本地缓冲区减少外部存储器访问 | 84 | 21 | 13800 | 16967 |
| 循环并行化(仅限卷积层) | 84 | 21 | 15363 | 18653 |
| 数据并行化 4×4(仅卷积层) | 86 | 43 | 22335 | 27020 |
| 最终版本 | 90+ | 63 | 32764 | 33674 |
各优化版本资源使用情况对比
值得注意的是,虽然性能提升了400多倍,但资源增量最大的DSP仅从 20 增加到 63(约3.15倍)。尤其是任务并行化和循环并行化,几乎未增加额外资源就显著提升了性能,是非常高效的优化手段。
常见问题: “为什么最终版本的BRAM显示为90+?还能进一步优化吗?”
答案: 90+表示综合工具报告的使用量超过90但未精确统计。当前FPGA内部仍有大量空闲资源,可以继续应用优化。例如,可以在内核内部进一步提取数据并行性,或者复制整个内核以利用帧间并行性。需要注意的是,单纯增加并行度可能使时序收敛变得困难,此时可以考虑采用后一种方法(复制内核)。
总结与展望
本次实验基于 MNIST 数据集(图像尺寸 28×28)和一个非常轻量级的网络模型。如果迁移到真实场景,模型规模和计算量会大幅增加:
- 图像分辨率:28×28 → 几百到几千像素
- 网络层数:2层(卷积+全连接)→ 几十到几百层
粗略估算,真实模型的计算量可能是本示例的 1000 到 100 万倍。如果仅增加1000倍,当前配置的运算单元(DSP、LUT)仍能在几十毫秒内完成推理;但如果增长更多,要达到60fps的实时处理就会非常困难。为此,实际工程中通常会结合量化和剪枝等技术来降低计算成本。下一篇(也是本系列的最后一篇)将详细介绍这些技术,敬请期待。
代码存储库请参考文末提供的链接(本教程未直接附链接,请回顾系列文章)。

