为什么在CNN中使用GEMM的im2col方法比使用SIMD的方向实现方法更高效

Jog*_*ong 6 memory floating-point instruction-set cpu-architecture conv-neural-network

卷积层是卷积神经网络(CNN)中计算量最大的部分。目前实现卷积层的常见方法是将图像扩展为列矩阵(im2col)并使用现有的并行通用矩阵乘法(GEMM)库。然而im2col操作需要加载和存储图像数据,并且还需要另一个内存块来保存中间数据。

如果我需要优化卷积实现,我可能会选择用SIMD指令直接实现。这种方法不会产生任何内存操作开销。

非常规律的内存访问模式所带来的好处超过了浪费的存储成本。

来自以下链接,在链接末尾

https://petewarden.com/2015/04/20/why-gemm-is-at-the-heart-of-deep-learning/

所以我希望知道原因。浮点运算可能需要更多指令周期吗?或者输入图像不太大,因此可能会残留在缓存中,并且内存操作不需要访问DDR并且消耗更少的周期。

Pet*_*des 3

缓存阻塞 GEMM 是可能的,因此您主要获得 L1 缓存命中(另请参阅每个程序员应该了解内存什么?)。

在典型的 x86 CPU 上安装大型共享 L3 缓存并不足以提高效率。每核 L2 缓存通常为 256kiB,甚至比 32kiB L1d 缓存还要慢。

与 CPU 核心时钟相比,内存延迟非常慢,但如今内存/缓存带宽在快速 DDR4 或 L3 缓存命中中并不可怕。(但就像我说的,对于具有良好缓存阻塞/循环平铺的 matmul,如果您仅动态转置部分输入矩阵,则可以在 L1d 中仍然很热时重用数据。减少核外带宽要求对于高效也很重要matmul,不仅仅是转置一个,使其列在内存中是连续的。)

除此之外,对内存的顺序访问对于高效 SIMD 至关重要(加载多个连续元素的向量,让您可以float使用一条 CPU 指令对 4 或 8 个打包元素进行乘法/加法/任意操作)。即使矩阵小到足以容纳 L1d 缓存 (32kiB),在行主矩阵中向下跨列也会损害吞吐量。