【问题标题】:Best approach for convolution of multiple small matrices using CUDA使用 CUDA 对多个小矩阵进行卷积的最佳方法
【发布时间】:2013-07-31 02:16:03
【问题描述】:

我需要使用小矩阵和内核进行多次卷积,我希望利用 GPU 的众多处理器能够尽快完成。

问题如下:我有许多矩阵(~1,000 到 ~10,000)或相对较小的尺寸(~15x15 到 1x1 - 如标量),以及一定数量的卷积掩码(~20 到 1)。我需要用每个卷积掩码卷积所有矩阵 示例:

A; %5,000 matrices of size 10x10, A(i) = a 10x10 matrix
B; 10 matrices of size 5x5, B(k) = a 5x5 matrix
res(j)=conv(A,B(1)); %res(j) is the result of convolving all 5,000
%matrices in A by the j'th kernel B(j)

目标是尽快计算 res(1),...,res(10)

我想听听有关如何实现最有效算法的建议。 基于 FFT 的卷积可能太慢了。

到目前为止,我看到的每个实现都是针对 2d 卷积,意在对 2 个大矩阵进行卷积,而我需要对许多小矩阵进行卷积。

我现在对 CUDA 编程知之甚少,但我正在学习中。

我希望自己解决这个问题,但由于时间限制,我不得不在学习如何在 CUDA 中编码的同时寻求任何有经验的人可以给我的建议。

谢谢!

附言任何指向适合我目的的实现的指针都非常感谢。我是一名大学生,这是一个小型研究项目,所以我不需要支付任何费用......

【问题讨论】:

  • 这个问题对于 GPU 来说并不理想,因为矩阵的尺寸很小。根据在 GPU 上为小矩阵实现批处理求解器的经验,我建议每个矩阵使用一个线程块来处理较大的矩阵,而每个矩阵一个线程来处理非常小的矩阵。您必须通过实验找到两种方法之间的切换点,它可能在维度 7 和维度 10 之间。
  • 谢谢。我以为几乎没有人需要这种东西,但我很高兴看到至少有人实现了这种东西。你碰巧知道我在哪里可以找到一个非常快速的 CUDA 实现来解决这样的问题吗?我已经看过并找不到任何东西,但是如果那里有一个非常好的实现,那就太好了。我不希望我的代码会像那里更有经验的 CUDA 程序员那样快(而现在,我对这个主题几乎一无所知,所以任何人都会比我更有经验......)
  • 批量求解器和矩阵逆代码可从 NVIDIA 的注册开发者网站下载。我知道没有批处理卷积代码,我只是根据矩阵大小和数量的相似性概述了可能的分区。由于卷积工作是在一个小型学生研究项目的背景下进行的,因此似乎这是一个通过自己实现此功能来获得经验的好机会。
  • 我愿意,但这不是项目的重点。卷积在我的代码中只需要大量时间。本来应该用别人写的高度优化的代码,结果失败了,我也没有多少时间了……

标签: cuda gpgpu convolution


【解决方案1】:

我不会假装对你的问题给出最终答案,但我想指出几点:

  1. 正如您所提到的,第一种可能性是使用 FFT 方法。这条线上的一个问题是(如果我错了,请纠正我)cuFFT 库主要是为处理大型矩阵而设计的,因此要从这种方法中取得丰硕成果,需要开发对小型矩阵有效的 FFT 例程。我只是想指出有一些此类算法,请参见例如论文:Small Discrete Fourier Transforms on GPUs。我对 CUDA FFT 在指定类型的小矩阵上的性能没有直接经验,但也许这对您来说可能很有趣,因为掩码矩阵的数量很少(10),因此您可以“回收”它们的 FFT用于大量卷积 (5000)。
  2. 如果您决定不使用 FFT 方法,那么,如果您的 GPU 架构具有计算能力 >=3.5,那么 动态并行性 可能是计算卷积的理想选择。如果您将每个卷积矩阵元素的评估视为插值,那么您将遇到大小为15x15 的插值问题,动态并行可能会有所帮助,请参阅帖子:Benefit of splitting a big CUDA kernel and using dynamic parallelism

【讨论】:

    【解决方案2】:

    一种方法是使用我正在研究的 ArrayFire 的 GFOR loop

    只要不耗尽 GPU 内存,您可以将任意数量的小型 convolutions 平铺到一个大型内核启动中,如下所示:

    array x = randu(5);      // the input
    array y = randu(m,5);    // the output
    array f = constant(1,3); // the kernel
    gfor (array k, 0, m-1) {
        y(span,k) = convolve(x,f);
    }
    

    祝你好运!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-05-01
      • 2012-07-04
      • 2016-11-01
      • 2012-10-21
      • 1970-01-01
      • 2015-06-17
      • 1970-01-01
      相关资源
      最近更新 更多