目录
博客:blog.shinelee.me | 博客园 | CSDN
随便翻一翻流行的推理框架(加速器),如NCNN、NNPACK等,可以看到,对于卷积层,大家不约而同地采用了Winograd快速卷积算法,该算法出自CVPR 2016的一篇 paper:Fast Algorithms for Convolutional Neural Networks。
本文将尝试揭开Winograd算法的神秘面纱。





整个计算过程在逻辑上可以分为4步:
注意,这里写成矩阵形式,并不意味着实现时要调用矩阵运算的接口,一般直接手写计算过程速度会更快,写成矩阵只是为了数学形式。


将卷积核的元素拉成一列,将输入信号每个滑动窗口中的元素拉成一行。注意图中红线划分成的分块矩阵,每个子矩阵中重复元素的位置与一维时相同,同时重复的子矩阵也和一维时相同,如下所示



此时,Winograd算法的乘法次数为16(上图4×4),而直接卷积的乘法次数为36,降低了2.25倍的乘法计算复杂度。
要将Winograd应用在卷积神经网络中,还需要回答下面两个问题:
第一个问题,在实践中,会将input feature map切分成一个个等大小有重叠的tile,在每个tile上面进行winograd卷积。
第二个问题,3维卷积,相当于逐层做2维卷积,然后将每层对应位置的结果相加,下面我们会看到多个卷积核时更巧妙的做法。
这里直接贴上论文中的算法流程:

整体仍可分为4步,
算法流程可视化如下,图片出自论文Sparse Winograd Convolutional neural networks on small-scale systolic arrays,与算法对应着仔细推敲还是挺直观的。

注意图中的Matrix Multiplication,对应3维卷积中逐channel卷积后的对应位置求和,相当于\((m+r-1)^2\)个矩阵乘积,参与乘积的矩阵尺寸分别为\(\lceil H / m\rceil\lceil W / m\rceil \times C\)和\(C \times K\),把Channel那一维消掉。