2013-06-30 100 views
1

我对GPU编程和C++ AMP相当陌生。任何人都可以制作一个通用优化的2D图像卷积滤镜吗?下面列出了我迄今为止的禁食版本。以某种方式平铺可以做得更好吗? 这个版本的工作原理比我的CPU执行速度快很多,但我希望能够更好地实现它。使用C++ AMP优化二维卷积滤波器

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

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

这包括几个不同的实现。样本是为书面讨论的,与它们相关的权衡会被讨论。

对于最小帧处理器设置(1个简化器相和1:1的 边框宽度),有共享存储器访问不足以平铺存储器的 趁。通过比较C++ AMP简单模型 (4.9毫秒)的卡通化阶段和运行在单个GPU上的平铺模型(4.2毫秒)所花费的时间,可以清楚地看出这一点。你 会希望平铺的实现更快地执行,但是 它是可比较的。对于默认和最大帧处理器设置, 平铺内存变得更有益,并且平铺模型处理器 执行得比简单模型处理器更快。

也有类似的问题在这里:

Several arithmetic operations pararellized in C++Amp

我张贴一些代码有这说明具有可变大小的过滤器。

+0

感谢您的提示,但该示例仅适用3x3卷积过滤器。而且,当我读到本书第253页上的性能表时,平铺在单个GPU上的平均情况下并没有真正提高速度。 –

+0

本书的结论似乎是正确的。随着过滤器大小的增加,您应该从tile_static内存中看到更多好处。过滤器越大(在合理范围内),您将可以使用更多的内存加载到更快的tile_static中。 –

+0

使用可变大小的过滤器参考更新了答案。 –