读 ncnn 源码(XXV):`fuse_deconvolution_add`——合并反卷积层的偏置链
读 ncnn 源码(XXV):fuse_deconvolution_add——合并反卷积层的偏置链
在本系列的前几篇中,我们已经系统性地分析了
ncnnoptimize如何融合Convolution,ConvolutionDepthWise后续的BatchNorm,Mul,Add等线性操作。为了确保优化策略的完整性,ncnn 也为反卷积层 (Deconvolution) 提供了类似的融合能力。继上一篇分析fuse_deconvolution_mul之后,本篇我们将聚焦于fuse_deconvolution_add,探讨其如何合并反卷积层后的逐通道加法操作。
TL;DR
- 目标: 将
Deconvolution层后接一个执行逐通道加法 (Per-Channel Bias Addition,由BinaryOp(Add)+MemoryData实现) 的操作进行融合。 - 模式匹配: 查找
Deconvolution -> BinaryOp结构,附加条件与fuse_convolution_add完全一致:BinaryOp必须是Add(op_type == 0),非标量 (!with_scalar),且第二输入来自形状匹配通道数的MemoryData向量(支持[channels]或[1, 1, channels]等广播形式)。 - 数学原理: 与
fuse_convolution_add完全一致。融合公式为:- 新权重 (权重不变)。
- 新偏置 (将
MemoryData的偏置向量 加到Deconvolution的原有偏置 上)。
- 代码实现: 几乎与
fuse_convolution_add完全相同。- 从
memorydata->data提取偏置向量B。 - 如果
Deconvolution没有偏置 (bias_term == 0),则将B设为其新偏置。 - 如果已有偏置 ,则将
B逐元素地加到deconvolution->bias_data上。
- 从
- 图结构修改: 将
Deconvolution层的top指向原BinaryOp的top,更新blob的producer,并将BinaryOp标记为"ncnnfused"。 - 效果: 消除了
BinaryOp层引入的冗余加法计算和内存访问,将偏置合并到Deconvolution层中,进一步优化计算图。
1. 融合动机:简化连续偏置操作的普遍性
Deconvolution 作为一种线性变换 ,其输出可能包含偏置项 。如果后续 BinaryOp 层仅执行逐通道加法 (其中 来自 MemoryData),则这两个加法可以合并为 。将合并后的偏置存入 Deconvolution 层,即可在推理时跳过 BinaryOp,实现优化。
2. 代码实现:复用偏置合并逻辑
fuse_deconvolution_add 的代码实现与 fuse_convolution_add 高度一致,仅层类型匹配不同,再次验证了该融合逻辑的通用性。
1 | int NetOptimize::fuse_deconvolution_add() |
关键点:
- 模式匹配: 查找
Deconvolution -> BinaryOp(Add)结构,且第二个输入来自符合广播条件的MemoryData。 - 参数更新: 将
MemoryData中的偏置数据bias_data(向量B) 加到deconvolution->bias_data(向量 ) 上。如果 不存在,则直接用B初始化。反卷积核权重不发生改变。 - 图修改: 标准的重定向连接 + 标记融合操作。
3. 意义:补全反卷积优化链
fuse_deconvolution_add Pass 的加入,补全了 ncnn 对反卷积层后接常见线性操作(BN, Mul, Add)的融合优化链条。这确保了无论网络结构如何设计或转换而来,只要存在可合并的线性计算,ncnnoptimize 都能尽可能地将其简化,从而提升最终的推理性能。
4. 结语
fuse_deconvolution_add 是 ncnn 图优化工具箱中,针对反卷积线性链优化的又一具体实现。它通过简单的偏置项合并,有效消除了冗余的逐通道加法运算。这一系列针对不同卷积变体(标准、深度、反卷积)及其后接线性操作(BN, Scale, Mul, Add)的精细化融合 Pass,共同构成了 ncnnoptimize 强大的模型“精炼”能力的核心,是 ncnn 实现端侧高性能推理的重要保障。





