关于加入 bias 优化的想法

源码

单通道,卷积核大小为 , 在这种情况下,输出仅仅是对图像中的每一个像素乘以一个系数。
以下源码是单通道部分的 Neon 实现.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
asm volatile(
"pld [%2, #256] \n"
"vld1.f32 {d4-d7}, [%2 :128]! \n"
"0: \n"
"pld [%1, #256] \n"
"vld1.f32 {d0-d3}, [%1 :128] \n"
"vmla.f32 q0, q2, %q6 \n"
"vmla.f32 q1, q3, %q6 \n"
"pld [%2, #256] \n"
"vld1.f32 {d4-d7}, [%2 :128]! \n"
"subs %0, #1 \n"
"vst1.f32 {d0-d3}, [%1 :128]! \n"
"bne 0b \n"
"sub %2, #32 \n"
: "=r"(nn), // %0
"=r"(outptr), // %1
"=r"(r0) // %2
: "0"(nn),
"1"(outptr),
"2"(r0),
"w"(_k0) // %6
: "cc", "memory", "q0", "q1", "q2", "q3"
);

bias

这里 bias 是在代码中循环开始前使用 Mat::filloutput 初始化为 bias 实现。
现在优化为在卷积计算过程后中使用 Neon 向量运算指令加到 output 中,理论上运算速度会快一点。
代码量不会很多,问题只是应该将 bias 的向量运算加在何处,源代码中的实现有八通道并行部分,四通道并行部分,还有就是最简单的单通道并行部分。

先从单通道开始吧

  • 单通道 bias 指令已经写完,为了测试注释掉之前全部八通道和四通道并行部分,全部跑单通道部分,出现误差,误差还挺大。

改 bug 改到怀疑人生

bias 是不能放在卷积运算过程中的,这样会造成 bias 的重复,实际上 bias 只需运算一次即可。只能讲 bias 运算放在循环之外,可是这样实现也就与将 fill 展开无异。

在实现中,最后一次循环是单独拿出来实现的,为了方便与 ReLU 层融合,可以将 bias 计算添加到这里。

bug 已找到,当注释掉 out.fill 这一行时,out 对象中为随机值,所以后面的 fmla 指令将计算结果与随机值累加,所以会导致运算出错,将 out.fill 变为 out.fill(0) 后测试通过。

那么当前的目标就是当第一次运算时不与之前结果累加直接赋值即可。

那么剩下的实现就应该不会有问题了