【问题标题】:Optimizing 2D convolution filter with C++ AMP使用 C++ AMP 优化 2D 卷积滤波器
【发布时间】:2013-06-30 20:35:13
【问题描述】:

我对 GPU 编程和 C++ AMP 还很陌生。任何人都可以帮助制作通用优化的二维图像卷积滤波器吗?到目前为止,我的禁食版本如下所示。可以以某种方式通过平铺做得更好吗? 这个版本运行起来比我的 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 的幂)。

【问题讨论】:

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


    【解决方案1】:

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

    这包括几个不同的实现。编写示例的书中讨论了与它们相关的权衡。

    对于最低帧处理器设置(1 个简化器阶段和 边框宽度为 1),共享内存访问不足 利用平铺内存。这通过比较清楚地表明 C++ AMP 简单模型的卡通化阶段所用的时间 (4.9 ms) 和在单个 GPU 上运行的平铺模型 (4.2 ms)。你 期望平铺实现执行得更快,但是 这是可比的。对于默认和最大帧处理器设置, 平铺内存变得更有益,平铺模型处理器 比简单模型的执行速度更快。

    这里有一个类似的问题:

    Several arithmetic operations pararellized in C++Amp

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

    【讨论】:

    • 感谢您的提示,但该示例仅应用了 3x3 卷积过滤器。此外,当我阅读本书第 253 页的性能表时,平铺在单个 GPU 上的平均情况下并没有真正提高任何速度..
    • 这本书得出的结论似乎是正确的。随着过滤器大小的增加,您应该会看到 tile_static 内存带来的更多好处。过滤器越大(在合理范围内),您将能够更多地使用加载到更快 tile_static 中的内存。
    • 使用可变大小过滤器参考更新答案。
    猜你喜欢
    • 2020-05-26
    • 2020-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-24
    • 1970-01-01
    • 1970-01-01
    • 2023-03-16
    相关资源
    最近更新 更多