我要感谢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的可移植性非常好。
谢谢!
答案 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路径上的全局负载存在一些性能问题。这些将通过更新得到改善。