图解ncnn实现Winograd卷积
前言
上一篇讲了Winograd的基本实现思路, 提到ncnn的实现是使用结论公式描述计算的流程, 用固定已知系数的加法代替矩阵乘法, 除此之外, ncnn的实现还涉及到一系列的内存重排配合SIMD操作提高效率. 本文用多幅图描述ncnn实现Winograd的详细流程. 希望能够帮助大家更好的理解.
流程概述
Y = A T [ ( G g G T ) ⊙ ( B T d B ) ] A = A T [ U ⊙ V ] A = A T M A (1) Y=A^T[(GgG^T)⊙(B^TdB)]A =A^T[U⊙V]A=A^TMA \tag{1} Y=AT[(GgGT)⊙(BTdB)]A=AT[U⊙V]A=ATMA(1)
回顾一下公式1, 其中 g g g代表卷积核, d d d代表卷积输入, Y Y Y代表卷积输出, 其余都为已知矩阵. 二维Winograd卷积的实现分为4步, 分别是:
- kernel_transform对应公式中的 U = G g G T U=GgG^T U=GgGT
- input_transform对应公式中的 V = B T d B V=B^TdB V=BTdB
- multi对应公式中的 M = U ⊙ V M=U⊙V M=U⊙V
- ouput_transform对应公式中的 Y = A T M A Y=A^TMA Y=ATMA
本文分析的是ncnn的Winograd实现函数包括conv3x3s1_winograd64_transform_kernel_neon5和conv3x3s1_winograd64_neon5, 对应的Winograd的 F ( 6 , 3 ) F(6,3) F(6,3), 即每个tile块的输出尺寸是[6x6], 卷积核尺寸是[3x3], 输入尺寸是[8x8].
步骤一: kernel_transform
step 1

对于一个nchw排布的kernel, 先根据公式 U = G g G T U=GgG^T U=GgGT对3x3的卷积核 g g g进行了转换得到8x8的尺寸. 其实这个过程是可以推理之前做好存储起来的, 所以即使用最慢的矩阵乘法也是可以的.
G = [ 1 0 0 − 2 9 − 2 9 − 2 9 − 2 9 2 9 − 2 9 1 90 1 45 2 45 1 90 − 1 45 2 45 32 45 16 45 8 45 32 45 − 16 45 8 45 0 0 1 ] G T = [ 1 − 2 9 − 2 9 1 90 1 90 32 45 32 45 0 0 − 2 9 2 9 1 45 − 1 45 16 45 16 45 0 0 − 2 9 − 2 9 2 45 2 45 8 45 8 45 1 ] (2) G = \left[ \begin{matrix} 1 & 0 & 0\\ -\frac{2}{9} & -\frac{2}{9} & -\frac{2}{9} \\ -\frac{2}{9} & \frac{2}{9} & -\frac{2}{9} \\ \frac{1}{90} & \frac{1}{45} & \frac{2}{45} \\ \frac{1}{90} & -\frac{1}{45} & \frac{2}{45} \\ \frac{32}{45} & \frac{16}{45} & \frac{8}{45} \\ \frac{32}{45} & -\frac{16}{45} & \frac{8}{45} \\ 0 & 0 & 1\\ \end{matrix} \right] \qquad G^T = \left[ \begin{matrix} 1 & -\frac{2}{9} & -\frac{2}{9} & \frac{1}{90} & \frac{1}{90} & \frac{32}{45} & \frac{32}{45} & 0\\ 0 & -\frac{2}{9} & \frac{2}{9} & \frac{1}{45} & -\frac{1}{45} & \frac{16}{45} & \frac{16}{45} & 0\\ 0 & -\frac{2}{9} & -\frac{2}{9} & \frac{2}{45} & \frac{2}{45} & \frac{8}{45} & \frac{8}{45} & 1\\ \end{matrix} \right] \tag{2} G=⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡1−92−929019014532453200−9292451−4514516−451600−92−924524524584581⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤GT=

本文深入解析ncnn库中Winograd卷积的实现,通过图解和代码分析详细阐述了kernel_transform、input_transform、multi和output_transform四个步骤。ncnn利用矩阵变换和内存重排优化了Winograd算法,减少了矩阵乘法,提高计算效率。文章通过实例展示了如何将3x3卷积核和输入数据转换为适合SIMD操作的格式,并最终得到卷积结果。

3479

被折叠的 条评论
为什么被折叠?



