我对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的幂次方)。
感谢您的提示,但该示例仅适用3x3卷积过滤器。而且,当我读到本书第253页上的性能表时,平铺在单个GPU上的平均情况下并没有真正提高速度。 –
本书的结论似乎是正确的。随着过滤器大小的增加,您应该从tile_static内存中看到更多好处。过滤器越大(在合理范围内),您将可以使用更多的内存加载到更快的tile_static中。 –
使用可变大小的过滤器参考更新了答案。 –