多个小卷积:图像处理

时间:2013-08-19 15:49:49

标签: image-processing cuda

我正在编写一个CUDA程序,它将尝试在基本图像中定位大约35个子图像或图案。每个子图像(图案)只能存在于基本图像的小区域(例如10×10像素窗口)中。子图像的大小从1000到10000像素不等。基本图像为640x480像素。

我这样做是通过将子图像与基本图像的子部分进行卷积,并且如果卷积结果小于阈值,则认为是匹配。我必须为每个子图像做大约100次卷积(因为我只检查一个10x10的允许位置窗口)。

第一个问题:这是否已实施,是否可在开源中使用?

第二个问题:哪个是更好的实施策略?

  1. 粗粒度:每个CUDA线程对基本图像内的子图像进行完全卷积。每个子图像和位置都有一个CUDA线程。
  2. 细粒度:每个CUDA线程计算卷积的一个分量(像素):因此,CUDA线程将子图像的像素乘以基本图像的适当像素。然后,使用syncblock()对这些倍数求和。
  3. 更新:我采用了两种方法。我认为最好的方法是方法一的变体,我将较大的子图像分成较小的子图像。现在所有子图像的大小大致相同(例如,1024像素)。然后每个CUDA线程对单个位置进行完全卷积。完成后,我将所有结果发送给主机,主机负责将中间件重新组合在一起(对于分成较小部分的子图像)。优点是所有CUDA线程执行相同的工作量。这似乎是第二种方法的两倍,这是有问题的,因为子图像的大小不同。

1 个答案:

答案 0 :(得分:1)

我建议你为每个子图像和位置使用1个cuda线程块(包含多个cuda线程)。

由于您的子图像大小不同,因此批量处理1个内核中的所有子图像可能不是一个好的选择。您可以设计一个内核来对子图像进行一次完全卷积,并为每个子图像调用35次。

在内核中,网格包含多个线程块,其数量等于允许位置的数量。然后,每个线程块计算子图像与基本图像的给定位置之间的像素倍数之和。

这类似于你的策略2.主要区别在于每个线程可以计算多个像素,而内核只使用一个线程块来进行求和,这不需要通过全局内存在线程块之间进行同步。

假设您的子图像有2000像素,允许的位置是10x10。您可以创建一个包含100个块的内核,每个块包含256个线程。块中的256个线程将执行2000倍像素的并行和。

<强>更新

您提出的方法可能有两个问题,

  1. 每个内核的线程太少。正如你所描述的那样,你的内核可能有10x10 = 100个线程用于允许的位置,每个线程总计大约1024个像素的倍数。通常,内核中每个块至少需要32个线程块和64~256个线程才能充分利用GPU。
  2. 更多的内核启动通常意味着更多的启动开销和更低的速度,因此将子图像划分为较小的图像并不是一个好的选择。
  3. 二叉树式并行减少实际上比线性减少更快。你可以在这里找到并行缩减示例代码

    http://docs.nvidia.com/cuda/cuda-samples/index.html#cuda-parallel-reduction

    这里有一份好的白皮书

    http://docs.nvidia.com/cuda/samples/6_Advanced/reduction/doc/reduction.pdf