今年企业命题卡延迟卡得很死,我们队伍用高云GW5A跑轻量CNN,端到端测出来38ms,评委说超了。想问下做过类似题目的同学,图像预处理、卷积加速、后处理这三段该怎么拆流水线才能压到20ms以内?是优先做层间流水还是先砍分辨率?
2026年FPGA大赛企业命题要求「边缘AI推理延迟低于20ms」,用高云GW5A做手势识别的队伍该怎么拆分流水线?
5 个回答

先说结论:38ms 到 20ms 不是靠「把三段各优化一点」凑出来的,而是要找到真正的那一段瓶颈,把它的串行时间打散。多数队伍的第一反应是砍分辨率,我个人建议先别动这个,因为分辨率一砍,手势识别的准确率会掉得很直接,评委那边精度也是要看的,你延迟达标但识别率崩了照样扣分。
正确顺序应该是先做测量,把端到端 38ms 拆成三段各自的耗时。常见情况是:预处理(去噪、灰度、缩放)如果是逐像素串行做,很容易吃掉 8~12ms;卷积加速段如果层间没有流水,每层等上一层写完才启动,中间的空转和 DDR/BRAM 读写往返会吃掉大头;后处理(NMS、分类输出、坐标映射)通常最轻,2~4ms。你先把这三段测出来,谁最大就先动谁。
假设卷积段是大头,那核心思路就是层间流水加行缓存。层间流水的意思是:第 N 层在算的时候,第 N+1 层不要等它整帧算完,而是按行或按块消费它的输出。要达到这个效果,中间 Feature Map 不要往 DDR 里写,用片上 BRAM 做乒乓缓冲,配合行缓存(line buffer)让下一层一开始就能吃到数据。这样重叠之后,理论加速比可以接近层数,实际因为层间数据依赖和带宽限制,能拿到 1.5~2 倍就不错了。高云 GW5A 的 BRAM 和 DSP 资源有限,你要算清楚每层特征图大小能不能塞进片上,塞不下就得降通道数或者分块。
如果预处理是大头,那就把它也做成流水的:图像进来一边做灰度/二值化,一边往行缓存里灌,不要先存整帧再处理。缩放如果能用最近邻或者整数倍降采样,比双线性省很多。分辨率确实要降的话,建议降到刚好满足手势识别的下限,比如从 640×480 降到 320×240 甚至 224×224,同时把数据位宽从 8bit 往 4bit 量化方向考虑,位宽砍一半带宽和乘法器压力都小一半。
还有一个容易被忽略的点:整体流水线的握手和反压。如果各段之间用 valid/ready 握手,但某一级处理慢,反压会把上游全堵住,流水线等于白做。你要保证最慢那一级的吞吐量就是整体吞吐,其他级都要能跟上。
最后给个可执行的路径:第一周先做 perf 分解,找出瓶颈段;第二周把卷积层间流水和行缓存搭起来,中间特征图尽量留片上;第三周再看预处理能不能流式化,分辨率位宽作为最后手段。你们现在测 38ms 是用什么方式测的,是仿真波形估算还是上板实测?这个会直接影响你判断哪段是真瓶颈。

我倾向先做层间流水,砍分辨率放后面。原因很简单:砍分辨率是拿精度换时间,评委既卡延迟也看识别率,你把 320×240 砍到 160×120 可能延迟够了但手势分不清了,得不偿失。层间流水是纯工程优化,不损失精度。
具体做法:把相邻两层之间的特征图放在片上 BRAM 里做乒乓,上一层按行产出,下一层按行消费,中间不要落 DDR。再在每层内部加行缓存(line buffer),让卷积窗口滑动时不用重复读。这样卷积段的串行时间会被大幅重叠掉。
预处理也顺手流式化,图像进来的同时就做灰度化和缩放,别先存整帧。后处理一般不是瓶颈,最后再看。
唯一要盯的是最慢那一级的吞吐,别让反压把流水线堵死。你们现在特征图是放 DDR 还是 BRAM?这个决定了层间流水好不好做。

先明确一点:38ms 里到底谁是大头,不测清楚就动手,基本等于赌博。我见过太多队伍一上来就砍分辨率,结果延迟是过了,识别率掉到评委摇头。所以主线应该是:先量出三段各自的耗时,再决定砍谁、留谁。
从工程因果上讲,端到端延迟大致等于三段串行时间之和减去能重叠掉的部分。预处理如果是整帧存完再做,那它天然是串行的;卷积段如果每层等上一层写完特征图才启动,那层与层之间就是硬串行;后处理一般最轻,但也可能因为CPU端搬运或者DDR反复读写而虚高。这三点里,卷积段往往是最大的一块,而它最大的浪费不是算力不够,是『等』。
所以主线我建议这样走:第一步,把每层特征图从DDR挪到片上做乒乓缓冲,上一层按行产出、下一层按行消费,中间不落外部存储。GW5A的BRAM够不够,取决于你现在的通道数和特征图尺寸,通常是够放几行而不是放整张图,这点要按行缓存的方式去规划。第二步,每层内部加行缓存,让卷积窗口滑动时复用数据,别每次都重新读。这两步是纯工程优化,不损失精度,收益却很明显,因为串行被重叠掉了。第三步,预处理也流式化:像素进来的同时就做灰度、缩放,不要先存整帧再处理。
至于砍分辨率和位宽,那是最后的弹药。分辨率先降一档看识别率能不能扛住,位宽从8位往int8甚至更低走,要看卷积累加会不会溢出。这两者都动精度,优先级排在流水线之后。
唯一要盯的是最慢那一级的吞吐,别让反压把整条流水线堵死,哪一级慢就先拆哪一级。你们现在特征图是落在DDR还是BRAM?这个决定了层间流水好不好做。

个人感觉你们现在最该做的不是『三段各优化一点』,而是先把38ms拆开看谁最重。拿个计时器或者片上计数器,把预处理、卷积、后处理三段的耗时分别打出来,一般会发现卷积段占一大半,而卷积段里又有相当一部分是层与层之间的等——上一层写完特征图,下一层才开始读,中间那段时间其实在空转。
如果确实是这种情况,主思路就是层间流水:相邻两层之间用BRAM做乒乓,让上一层按行产出、下一层按行消费,特征图不落DDR。再在每层内部加行缓存,卷积窗口滑动时数据复用,不用反复读。这两步不损失精度,收益却直接。预处理顺手流式化,图像进来就灰度加缩放,别先存整帧。
砍分辨率和位宽是备选,动了就影响识别率,留到流水线做完还不够再上。你们现在特征图是放片上还是DDR?

先说个容易被忽略的前提:企业命题卡的是端到端 20ms,不是某一段的加速比。所以你们真正要回答的问题是「这 38ms 里有多少是可以被重叠掉的串行时间」,而不是「哪一段能提速几倍」。这两个问法会导出完全不同的优化顺序。
从因果上讲,端到端延迟等于各段串行时间之和减去被流水重叠掉的部分。你们现在 38ms 大概率是三段各自独立跑、跑完一段再跑下一段的结构,也就是预处理存完整帧才开始卷积,卷积每层等上一层特征图写回 DDR 才启动,后处理再等卷积全部结束。这种结构下,延迟就是三段之和,任何一段单点优化收益都有限。
第一步一定是量时间,不是猜。用片上计数器或者 GPIO 翻转加示波器,把预处理、卷积、后处理各自的起止时刻打出来,再把卷积段按层拆开,看每层之间有没有空转。常见情况是卷积段占 20ms 以上,而里面相当一部分是层间等待和 DDR 往返,不是乘加本身不够快。
如果测出来确实是这个形状,主线就是层间流水加行缓存。层间流水的意思是相邻两层之间用片上 BRAM 做乒乓,上一层按行产出、下一层按行消费,特征图不落 DDR。每层内部再加 line buffer,让卷积窗口滑动时复用数据,避免重复读。这两步不损失精度,但能把大量串行等待变成重叠,通常是最划算的一刀。预处理顺手流式化,图像进来就灰度加缩放,别先存整帧。
砍分辨率和位宽我建议放到这条主线做完之后再评估。原因不是不能砍,而是它的代价直接落在识别率上,评委既卡延迟也看精度,先砍等于把风险提前兑现。真要砍,也是分辨率与位宽一起动、配合重训或量化校准,而不是单方面降。
你们现在卷积段内部是按层串行、每层特征图落 DDR 的吗?这个决定了层间流水能不能直接套上去。
发表回答
登录后可在本页底部提交回答