为什么这些Google图像处理示例Renderscript在Nexus 5中的GPU上运行速度较慢

时间:2013-12-04 18:17:35

标签: android gpgpu renderscript

我要感谢Stephen在上一篇文章中的快速回复。这是此帖Why very simple Renderscript runs 3 times slower in GPU than in CPU

的后续问题

我的开发平台如下

Development OS: Windows 7 32-bit
Phone: Nexus 5
Phone OS version: Android 4.4
SDK bundle: adt-bundle-windows-x86-20131030
Build-tool version: 19
SDK tool version: 22.3
Platform tool version: 19

为了评估Renderscript GPU计算的性能并掌握Renderscript使代码更快的一般技巧,我做了以下测试。

我使用标签android-4.2.2_r1.2检查了Google的Android开源项目中的代码。我之所以使用此标签,只是因为ImageProcessing测试样本在较新版本中不可用。

然后我在测试中使用了“base \ tests \ RenderScriptTests \ ImageProcessing”下的项目。我记录了在GPU上运行代码的性能以及CPU,性能如下所示。

                         GPU    CPU
Levels Vec3 Relaxed     7.45ms  14.89ms
Levels Vec4 Relaxed     6.04ms  12.85ms
Levels Vec3 Full        N/A     28.97ms
Levels Vec4 Full        N/A     35.65ml
Blur radius 25          203.2ms 245.60ms
Greyscale               7.16ms  11.54ms
Grain                   33.33ms 21.73ms
Fisheye Full            N/A     51.55ms
Fisheye Relaxed         92.90ms 45.34ms
Fisheye Approx Full     N/A     51.65ms
Fisheye Approx Relaxed  93.09ms 39.11ms
Vignette Full           N/A     44.17ms
Vignette Relaxed        8.02ms  46.68ms
Vignette Approx Full    N/A     45.04ms
Vignette Approx Relaxed 8.20ms  43.69ms
Convolve 3x3            37.66ms 16.81ms
Convolve 3x3 Intrinsics N/A     4.57ms
ColorMatrix             5.87ms  8.26ms
ColorMatrix Intrinsics  N/A     2.70ms
ColorMatrix Intinsics Grey  N/A 2.52ms
Copy                    5.59ms  2.40ms
CrossProcess(using LUT) N/A     5.74ms
Convolve 5x5            84.25ms 46.59ms
Convolve 5x5 Intrinsics N/A     9.69ms
Mandelbrot              N/A     50.2ms
Blend Intrinsics        N/A     21.80ms

表中的N / A是由完全精度或rs内在函数未在GPU上运行引起的。我们可以看到,在GPU上运行的13种算法中,其中6种在GPU上运行较慢。由于此类代码是由Google编写的,因此我认为这种现象值得研究。至少,“我认为代码将在GPU上运行得更快”,我从Renderscript and the GPU看到的并不存在。

我调查了列表中的一些算法,我想提两个。

在Vignette中,GPU的性能要好得多,我发现这是通过调用rs_cl.rsh中的几个函数来使用的。如果我注释掉这些功能,CPU将运行得更快(在极端情况下请参阅我之前的问题)。所以问题是为什么会发生这种情况。在rs_cl.rsh中,大多数函数都是数学相关的,例如exp,log,cos等等。为什么这样的函数在GPU上运行得更快,这是因为这些函数的实现实际上是高并行的,还是因为在GPU上运行的版本的实现优于在CPU上运行的版本?

另一个例子是conv3x3和conv5x5。虽然在这个测试应用程序中还有比Google版本更聪明的实现,但我认为Google的这种实现肯定不错。它尝试最小化加法运算并使用rs_cl.rsh中的一些简化函数,例如convert_float4()。所以一目了然,我认为它会在GPU上运行得更快。但是,它运行速度要慢得多(在Nexus 4和5上都使用Qualcomm的GPU)。我认为这个例子非常具有代表性,因为在实现中,算法需要访问当前像素附近的像素。这种操作在许多图像处理算法中非常普遍。如果像2D卷积这样的实现在GPU中不能更快,我怀疑还有很多其他算法会受到同样的影响。如果您能够确定问题所在并提出一些方法来更快地制定此类算法,我们将非常感激。

更普遍的问题是,鉴于我展示的测试结果,我想问一下人们应该遵循什么样的标准才能获得更高的性能并尽可能地避免性能下降。毕竟,性能的目标是Renderscript的第二个最重要的目标,我认为RS的可移植性非常好。

谢谢!

1 个答案:

答案 0 :(得分:5)

这个问题确实有两个答案。

1:不要相信有关GPU的炒作。对于某些工作负载,它们更快。但是,对于许多工作负载而言,差异很小或是负面的。你有至少2种不同的处理器类型,不用担心使用哪种类型,只要担心性能是你想要的。

2:对于性能调优,我会专注于算法并避免慢速操作。例子:

  • 当float提供足够的精度时,首选float加倍。

  • 当您不需要符合IEEE-754时使用RS_FP_RELAXED

  • 首选乘法除法

  • 使用native_ *(例如:native_powr)代替精度足够的完整精度例程

  • 在rsSample或rsGetElementAt上使用rsGetElementAt_ *。在许多情况下,get的类型版本比一般版本更快,并且比rsSample快得多。

  • 来自脚本全局变量的
  • 加载通常比来自rs_allocation的加载更快。首选内核常量的全局。

3:目前Nexus(4,5,7v2)GPU路径上的全局负载存在一些性能问题。这些将通过更新得到改善。