我们队伍用高云GW2A系列做电赛的人脸检测,YOLO-tiny量化后DSP用掉90%,BRAM也爆了。还剩三天就要交作品,换芯片肯定来不及。现在想用移位寄存器代替乘法器、用查找表实现部分卷积核,但不知道具体怎么替换才能保证时序不崩。有没有人做过类似的资源硬抠?比如3×3卷积的乘加运算怎么拆成移位加法和LUT查找?替换后精度和速度大概会掉多少?求具体替换公式和资源对比,急!
FPGA大赛只剩三天,用高云FPGA做实时人脸检测,BRAM和DSP都爆了,怎么用移位寄存器和查找表硬抠资源?求具体替换公式
3 个回答

先说结论:三天时间别指望把YOLO-tiny完整重写成移位寄存器版。DSP爆90%说明卷积层是主凶,BRAM爆则多半是中间特征图缓存太多。个人建议优先级:先砍通道数或特征图分辨率(比如输入从224降到160),这是最直接的资源释放;其次才是把3×3卷积拆成移位加法。具体来说,量化后的权重如果都是8位整数,可以按位拆:y = wx = sum(w_i 2^i x),把w拆成二进制,每个非零位对应一次左移和累加。一个3×3卷积原本9次乘加,拆开后可能变成几十次移位加,但DSP占用归零,时序反而更可控,因为移位加是纯LUT+布线逻辑。LUT查表适合固定小卷积核,比如3×3权重共9个8位数,你可以把输入像素的相邻位组合成地址,预存部分积,但一般只对1×1卷积或少量系数这么做,全查表会爆LUT。精度上,移位加法是精确的,只要权重整数化没溢出就无损;查表法如果只取高4位输入,精度会掉2-3个mAP点。速度方面,DSP换成LUT后时钟频率可能降20-30%,但人脸检测实时性要求不高,30fps应该还能保。另外BRAM爆的话,把中间特征图改成行缓冲(移位寄存器实现)能省不少,但代码改动大。最后一天如果实在调不通,干脆降低检测阈值或者只跑单尺度,保交作品。你们用的是高云的哪个具体型号?不同容量的LUT数量影响挺大的。

我去年做过类似的事,不过用的是Xilinx,思路共通。你要明白一个关键点:DSP爆了不是必须全部替换,而是优先替换那些被重复调用的卷积层。YOLO-tiny里1×1卷积占大头,这个可以用LUT直接查表,因为1×1卷积本质是通道间的线性组合,如果权重固定且量化后位宽不高,你可以把输入像素的若干位拼成地址,预存计算结果。比如输入8位、输出8位,一个输出通道需要查256次表,但可以用分布式RAM实现,一个LUT6可以存64位,查表深度不够就拆成多级。3×3卷积才是DSP大户,这里用移位寄存器做行缓存是标准做法:用Shift Register(SRL16)存三行数据,每行延时一个时钟周期,然后并行取9个像素。乘加运算拆成移位加法的公式是:设权重w是带符号8位整数,拆成w = sign sum(b_i 2^i),其中b_i是二进制位。那么wx = sign sum(b_i (x << i)),每个非零位对应一次左移,累加即可。一个3×3卷积原本9次乘法,现在变成平均4-5次移位加(因为8位整数平均有4个非零位),这样DSP占用降为0,但LUT和FF占用会上升。你要注意时序,移位加法链容易变长,建议在每行累加后插入流水寄存器,或者用加法树结构。精度上,这种替换是精确的,前提是量化后权重没有溢出。速度上,纯LUT逻辑跑100MHz没问题,但原来DSP版本能到150MHz,所以总吞吐会略降。BRAM爆的话,建议把中间特征图直接流式处理,不要整帧缓存,用行缓冲加滑动窗口,这样BRAM只用存三行数据,能省80%。最后提醒:替换后一定要做仿真对比,特别是边界像素的时序对齐,不然容易出毛刺。你们现在用的是高云的哪个开发工具?不同版本对SRL16原语支持不一样,这会影响你写移位寄存器的方式。

别折腾公式了,三天时间直接砍输入尺寸和通道数,DSP和BRAM立刻降一半。移位加法只改最耗DSP的层,其他层留着,精度掉一点总比交不了作品强。你们检测目标是人脸,又不是COCO,160×160输入够用了。
发表回答
登录后可在本页底部提交回答