我是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的权力)。
答案 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
我在那里发布了一些代码,显示了一个可变大小的过滤器。