真实面经题目 · 原创解析
推理框架中卷积算子通常有哪些实现方式,如何按输入形状、硬件和延迟目标选型?
这题考推理框架里的卷积实现谱系,而不是卷积数学定义。回答要覆盖 direct、im2col/GEMM、implicit GEMM、Winograd、FFT、1x1/depthwise/group 专用 kernel,并说明选型受形状、batch、硬件、内存带宽、精度和端到端延迟影响。
真实面经题目 · 原创解析
这题考推理框架里的卷积实现谱系,而不是卷积数学定义。回答要覆盖 direct、im2col/GEMM、implicit GEMM、Winograd、FFT、1x1/depthwise/group 专用 kernel,并说明选型受形状、batch、硬件、内存带宽、精度和端到端延迟影响。
推理框架里的卷积实现通常不是一种。最基础的是 direct convolution,按 N、C、H、W、Kh、Kw 循环计算,适合小规模或特殊形状,但通用性能不一定最好。第二类是 im2col + GEMM,把滑窗展开成矩阵乘法,复用 BLAS/Tensor Core,但会产生较大临时内存和数据搬运。第三类是 implicit GEMM,不显式展开 im2col,而是在 kernel 内按 GEMM tile 组织访存和计算,很多 GPU 推理库常用这种思路。第四类是 Winograd,适合 3x3、stride 1 等小卷积核,可以减少乘法次数,但有变换开销和数值误差。第五类是 FFT convolution,适合大 kernel 或大特征图,但小 kernel 推理不一定划算。1x1 convolution 常退化成 GEMM,depthwise/group convolution 通常需要专用实现。实际选型要看输入输出通道、kernel size、stride/padding/dilation、batch size、layout、dtype、硬件缓存和 Tensor Core 支持,再通过 autotune 或 benchmark 选择。
Direct convolution 按定义遍历输出像素、输出通道、输入通道和卷积核位置,逻辑清晰、临时内存少、适配形状灵活。问题是通用循环很难充分利用矩阵乘法库、向量化单元和 Tensor Core,访存复用依赖手写优化。
im2col 把每个滑窗展开成矩阵列,再把卷积核展开成矩阵,用 GEMM 完成计算。好处是复用高度优化的矩阵乘法;代价是展开矩阵可能很大,额外占用内存并增加读写,小 batch 或大 feature map 时收益可能下降。
implicit GEMM 不真的生成完整 im2col 矩阵,而是在 GPU kernel 内按 GEMM tile 方式计算滑窗元素。它能利用分块、共享内存和向量化,又避免显式展开缓冲。cuDNN、TensorRT 等库会按 shape、dtype、layout 和硬件做算法选择。
Winograd 通过输入、权重和输出变换减少小卷积核乘法次数,典型适合 3x3、stride 1、通道数较多的层;FFT 把卷积转成频域乘法,更适合大 kernel 或大空间尺寸。它们都有变换开销和数值稳定性约束。
1x1 convolution 没有空间滑窗,本质接近每个像素位置的通道维矩阵乘法;depthwise convolution 每个通道独立,FLOPs 低但复用弱,容易 memory-bound;group convolution 介于二者之间,选型要看 group 数和分组后的矩阵规模。
卷积算法选择不能只看单层 FLOPs,因为真实延迟受 kernel launch、layout 转换、cache 命中、临时 buffer、融合机会、batch size 和并发调度影响。线上要用目标硬件上的 P50/P95 延迟、吞吐、显存峰值和数值误差评估。
显式展开会产生大量临时内存,并增加输入重复读写。对小 batch、大 feature map 或内存带宽紧张的推理场景,展开成本可能超过 GEMM 收益。
通常适合 3x3、stride 1、通道数较多、空间尺寸合适的卷积层。若卷积核大、stride/dilation 特殊、通道太少或精度要求高,收益会下降。
它计算量少,但数据复用有限,算术强度低,容易受内存带宽和 kernel launch 限制。优化更关注 layout、向量化和融合,而不只是减少乘法数。
一般根据 shape、dtype、layout、workspace 限制和硬件能力枚举候选算法,再用启发式或 benchmark 选择。生产还要考虑动态 shape、冷启动、workspace 峰值和跨版本稳定性。