跳到正文
Semiconductor Engineering· Mario Florea·· 4 小时前AI 评分22

如何将 Conv2D 转化为实用的 GPU 计算模式

Turning Conv2D Into A Practical GPU Compute Pattern

AI 导读

文章讲解如何把 Conv2D 当作结构化矩阵乘法来实现:NHWC 布局下 1×1 卷积可直接视为从 C_in 到 C_out 的矩阵乘,无需转置;3×3 卷积则拆成 9 组 C_in×C_out 贡献的累加。作者强调优化重点在循环顺序与缓存复用,而非先做指令级调优。

深度导读
文章从工程实现角度重新解释 2D 卷积:不把它当作独立的专用算子,而是看作与矩阵乘法高度相关的计算模式,从而复用成熟的执行模型、降低实现与维护成本。标准 Conv2D 的输入张量为 N×H×W×C_in,权重为 H_filter×W_filter×C_in×C_out,输出为 N×H_out×W_out×C_out。 最简情形是 1×1 卷积:每个空间位置的输入是一个长度 C_in 的特征向量,权重把它映射为长度 C_out 的输出向量。若输入已按 NHWC 存储,这些特征向量天然可视为矩阵的行,因此 1×1 卷积可直接当作从 C_in 到 C_out 的矩阵乘,输出仍为 NHWC,省去转置步骤,避免不必要的数据搬运。 滤波器扩大到 K×K 后,每个输出元素依赖多个空间位置。以 3×3 为例,每个输出位置需累加 9 组 C_in×C_out 的贡献,问题从“做一次矩阵乘”变成“反复做矩阵式累加并尽量减少内存浪费”。朴素实现算术利用率不低,但可能反复刷新并重载输入数据,此时循环顺序成为关键:重排循环嵌套可改善局部性、减少重复取数,而算术量不变。 文章给出了一段代表性内核结构:加载权重、计算输入坐标、向量化读取输入、同步本地内存、累加部分积,并配合向量化读取、本地内存暂存可复用权重、显式同步与线程级并行。边界处理上,零填充最常见,典型做法是在读取前检查坐标是否落在有效图像范围内;但热循环中的分支代价较高,可改为把越界读取重定向到零填充的哑缓冲区,把分支成本换成准备逻辑。滤波器越大通常提升输入复用,步长越大则降低相邻输出间的复用,二者都影响算术与内存流量的平衡。 作者总结的方法论是:先明确张量解释,识别可映射到矩阵乘的情形,尽量保持数据布局,优先优化循环顺序与缓存复用,并把填充、步长与边界逻辑当作影响性能的设计选择。常见误区包括误判瓶颈在算术而非内存流量、过早引入显式数据变换、把边界分支留在最热循环中、在验证缓存行为前先调指令细节。建议按数学层、布局层、执行层三层对齐来设计或评审 GPU 卷积内核。

来源:Semiconductor Engineering · semiengineering.com