我试图弄清楚某个问题是否适合使用CUDA将问题放在GPU上。
我本质上是在做一个基于一些边缘检测而改变的盒式过滤器。因此,基本上有8个案例针对每个像素进行测试,然后其余的操作发生 - 典型的平均计算等。在我的循环中是否存在这些switch语句会导致这个问题成为转向GPU的不良选择?
我不确定如何避免切换语句,因为这种边缘检测必须发生在每个像素上。我想整个图像可能会将边缘检测部分从处理算法中分离出来,并且您可以存储一个缓冲区,该缓冲区对应于每个像素使用哪个滤镜,但这似乎会为算法添加大量预处理。
编辑:只是为了给出一些上下文 - 这个算法已经编写好了,OpenMP已经被用来加速它的效果。但是,与GPU中的512核相比,我的开发盒上的8个核心相形见绌。
答案 0 :(得分:1)
边缘检测,平均计算和互相关可以实现为2D卷积。可以非常有效地在GPU上实现卷积(相对于CPU而言speed-up > 10, up to 100),尤其是对于大型内核。所以是的,在GPU上重写图像过滤可能是有意义的。
虽然我不会将GPU用作这种方法的开发平台。
答案 1 :(得分:1)
通常,除非您使用新的CUDA架构,否则您将需要避免分支。因为GPU基本上都是SIMD机器,所以由于分支机构错误预测,pipleline非常容易受到管道停滞的影响。
如果您认为使用GPU可以获得显着的好处,请做一些初步的基准测试以获得一个粗略的想法。
如果您想了解一下如何编写非分支代码,请转到http://cellperformance.beyond3d.com/并查看。
此外,调查在多个CPU内核上运行此问题可能也是值得的,在这种情况下,您可能需要查看OpenCL或Intel性能库(例如TBB)
另一个针对GPU的问题来源是图形,计算几何或其他方面,IDAV是数据分析和可视化研究所:http://idav.ucdavis.edu
答案 2 :(得分:1)
如果分支中存在空间一致性,分支实际上并不是那么糟糕。换句话说,如果您希望图像中彼此相邻的像素块通过相同的分支,则性能命中最小化。
答案 3 :(得分:0)
使用GPU进行处理通常会违反直觉;如果使用普通的串行代码完成效率明显低下,实际上是使用GPU并行执行的最佳方式。
下面的伪代码效率低(因为它为每个像素计算8个过滤值),但会在GPU上高效运行:
# Compute the 8 possible filtered values for each pixel
for i = 1...8
# filter[i] is the box filter that you want to apply
# to pixels of the i'th edge-type
result[i] = GPU_RunBoxFilter(filter[i], Image)
# Compute the edge type of each pixel
# This is the value you would normally use to 'switch' with
edge_type = GPU_ComputeEdgeType(Image)
# Setup an empty result image
final_result = zeros(sizeof(Image))
# For each possible switch value, replace all pixels of that edge-type
# with its corresponding filtered value
for i = 1..8
final_result = GPU_ReplacePixelIfTrue(final_result, result[i], edge_type==i)
希望这有帮助!
答案 4 :(得分:0)
是的,控制流通常会对GPU造成性能损失,无论是 if / switch'es / ternary operator ,因为对于控制流操作,GPU无法最佳地运行线程。所以通常的策略是尽可能避免分支。在某些情况下,IF可以用某些公式代替,其中IF条件映射到公式系数。但具体的解决方案/优化取决于具体的GPU内核...也许你可以显示确切的代码,由stackoverflow社区进一步分析。
修改强> 如果你感兴趣的话,我写的是convolution pixel shader。