一、课程导论:为什么需要FFT加速卷积?卷积的数学本质与计算瓶颈

大家好,欢迎来到《FFT加速卷积层计算实践》的第一章。

先问大家一个问题:你训练一个ResNet-50,跑一次前向传播,大概有多少次乘法?

答案是——接近40亿次。其中90%以上都花在卷积层上。

我第一次跑这个数字的时候,说实话,吓了一跳。那时候我在做一个人脸识别项目,模型跑一次推理要200多毫秒,根本没法落地。后来我仔细一分析,好家伙,卷积层占了180毫秒。

所以问题来了:卷积为什么这么慢?有没有办法让它快起来?

嗯,这就是我们今天要聊的核心——FFT加速卷积。

1.1 卷积的数学本质:你到底在算什么?

先别急着写代码。我们得先搞清楚卷积到底在干嘛。

从数学上讲,二维卷积的定义是这样的:

(f * g)[i, j] = Σ_m Σ_n f[m, n] · g[i-m, j-n]

看着有点抽象对吧?我换个说法。

你有一个输入图像,比如224×224。你有一个卷积核,比如3×3。卷积操作就是:把卷积核滑过图像的每一个位置,在每个位置上做一次逐元素乘法,然后求和。

说白了,就是「滑动窗口 + 点积」。

那计算量有多大呢?

输入尺寸 卷积核尺寸 输出通道数 单层乘法次数
224×224 3×3 64 约9亿次
112×112 5×5 128 约20亿次
56×56 7×7 256 约39亿次

看到没?一个7×7的卷积核,一层就要算39亿次乘法。而一个ResNet-152有超过150层。

你想想看,这得算到什么时候?

1.2 计算瓶颈:为什么卷积这么慢?

我总结了一下,卷积慢的原因主要有三个:

  • 计算密集:每个输出像素都要做K²次乘加,K是卷积核尺寸。K越大,计算量呈平方增长。
  • 内存访问不友好:卷积核在图像上滑动时,相邻窗口之间有大量重复的数据加载。我做过一个测试,3×3卷积的重复加载率高达67%。
  • 并行度受限:虽然卷积可以并行,但每个输出像素的计算依赖一个局部区域,导致GPU的线程利用率并不理想。

⚠️ 我曾经踩过的坑:

有一次我优化一个3D卷积网络,天真地以为用im2col + GEMM就能搞定。结果显存直接爆了——im2col把输入重复存储了9倍,一个256×256×64的特征图变成了256×256×576的矩阵。嗯,那次教训很深刻。

1.3 换个思路:时域卷积 = 频域乘积

好,问题摆在这了。有没有更聪明的办法?

有。而且这个办法来自一个非常经典的数学定理——卷积定理。

卷积定理说:时域上的卷积,等于频域上的逐元素乘积

用公式表达就是:

f * g = IFFT( FFT(f) ⊙ FFT(g) )

其中⊙表示逐元素乘法。

这意味着什么?

原本你要做K²次乘加,现在只需要做3次FFT(前向两次,反向一次)加上一次逐元素乘法。

而FFT的复杂度是O(N log N),逐元素乘法是O(N)。

当卷积核尺寸K比较大时,这个优势就非常明显了。

关键结论:

当K > 7时,FFT方法开始优于直接卷积。K越大,优势越明显。

比如一个11×11的卷积核,FFT方法可以快5-10倍。

1.4 一个直观的例子

我习惯用一个小例子来说明问题。

假设你有一个4×4的输入,一个3×3的卷积核。

直接卷积:你需要滑动4次(横向)× 4次(纵向)= 16个位置,每个位置做9次乘法。总共144次乘法。

FFT方法:

  • 对输入做FFT:O(16 log 16) ≈ 64次运算
  • 对卷积核做FFT:同样64次
  • 频域逐元素乘法:16次
  • IFFT:64次
  • 总共:约208次运算

咦?看起来反而更多了?

别急。这是因为例子太小了。当输入变成64×64,卷积核变成11×11时:

  • 直接卷积:64×64×121 ≈ 50万次乘法
  • FFT方法:3 × 64×64×log(64) + 64×64 ≈ 4.5万次运算

差了10倍以上。

💡 个人经验:

在实际项目中,我一般这样选:

  • 3×3卷积:用直接卷积(im2col或Winograd)
  • 5×5卷积:两者差不多,看具体硬件
  • 7×7及以上:无脑上FFT

当然,这只是经验值。具体还是要profile一下。

1.5 本章小结

好,我们来捋一下今天的内容:

  1. 卷积的本质:滑动窗口 + 点积,计算量随卷积核尺寸平方增长
  2. 计算瓶颈:计算密集、内存访问不友好、并行度受限
  3. FFT加速原理:利用卷积定理,把时域卷积变成频域乘积
  4. 适用场景:大卷积核(K≥7)时优势明显

下一章,我会带大家手写一个FFT卷积的Python实现。到时候你会看到,代码其实没你想的那么复杂。

嗯,今天就到这。有问题欢迎在评论区讨论。


公众号:蓝海资料掘金营,微信deep3321