使用C ++ AMP优化2D卷积滤波器

时间:2013-06-30 20:35:13

标签: filter bitmap 2d convolution c++-amp

我是GPU编程和C ++ AMP的新手。任何人都可以帮助制作一般优化的2D图像卷积滤镜吗?到目前为止,我禁食的版本如下所示。以某种方式平铺可以做得更好吗? 这个版本可以工作,并且比我的CPU实现快得多,但我希望它能更好。

void FIRFilterCore(array_view<const float, 2> src, array_view<float, 2> dst, array_view<const float, 2> kernel)
{
    int vertRadius = kernel.extent[0] / 2;
    int horzRadius = kernel.extent[1] / 2;

    parallel_for_each(src.extent, [=](index<2> idx) restrict(amp)
    {
        float sum = 0;
        if (idx[0] < vertRadius || idx[1] < horzRadius ||
            idx[0] >= src.extent[0] - vertRadius || idx[1] >= src.extent[1] - horzRadius)
        {
            // Handle borders by duplicating edges
            for (int dy = -vertRadius; dy <= vertRadius; dy++)
            {
                index<2> srcIdx(direct3d::clamp(idx[0] + dy, 0, src.extent[0] - 1), 0);
                index<2> kIdx(vertRadius + dy, 0);
                for (int dx = -horzRadius; dx <= horzRadius; dx++)
                {
                    srcIdx[1] = direct3d::clamp(idx[1] + dx, 0, src.extent[1] - 1);
                    sum += src[srcIdx] * kernel[kIdx];
                    kIdx[1]++;
                }
            }
        }
        else // Central part
        {
            for (int dy = -vertRadius; dy <= vertRadius; dy++)
            {
                index<2> srcIdx(idx[0] + dy, idx[1] - horzRadius);
                index<2> kIdx(vertRadius + dy, 0);
                for (int dx = -horzRadius; dx <= horzRadius; dx++)
                {                   
                    sum += src[srcIdx] * kernel[kIdx];
                    srcIdx[1]++;
                    kIdx[1]++;
                }
            }
        }
        dst[idx] = sum;
    });
}

绕过它的另一种方法当然是在傅立叶域中执行卷积,但是我不确定只要滤镜与图像(没有边长)相比相当小就会执行顺便说一句,这是2的权力)。

1 个答案:

答案 0 :(得分:1)

您可以找到Cartoonizer算法的完整实现。它在Codeplex上实现了几个基于模板的算法。 http://ampbook.codeplex.com/

这包括几种不同的实现。与样本相关的权衡将在书中为样本编写。

  

对于最小帧处理器设置(1个简化阶段和a   边框宽度为1),共享内存访问不足   利用平铺内存。通过比较,可以清楚地看出这一点   C ++ AMP简单模型的卡通化阶段所花费的时间   (4.9 ms)和在单个GPU上运行的平铺模型(4.2 ms)。您   我希望平铺的实现能够更快地执行,但是   它具有可比性。对于默认和最大帧处理器设置,   平铺的内存变得更有益,而平铺的模型处理器   执行速度比简单模型快。

这里有一个类似的问题:

Several arithmetic operations pararellized in C++Amp

我在那里发布了一些代码,显示了一个可变大小的过滤器。