我要感谢 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 编写的,因此我认为这种现象值得研究。至少,我从 Renderscript and the GPU 看到“我假设代码在 GPU 上运行得更快”在这里不成立。
我研究了列表中的一些算法,我想提两个。
在 Vignette 中,GPU 的性能要好得多,我发现这是通过调用 rs_cl.rsh 中的几个函数来使用的。如果我注释掉这些功能,CPU 将运行得更快(请参阅我之前在顶部的问题以了解极端情况)。所以问题是为什么会这样。在 rs_cl.rsh 中,大部分函数都与数学相关,例如exp, log, cos, etc. 为什么这样的函数在 GPU 上运行得更快,这是因为这些函数的实现实际上是高并行的,还是仅仅因为在 GPU 上运行的版本的实现比在 CPU 上运行的版本更好?
另一个例子是 conv3x3 和 conv5x5。虽然在这个测试应用程序中还有其他比谷歌版本更聪明的实现,但我认为谷歌的这个实现肯定不错。它试图最小化加法运算并使用 rs_cl.rsh 中的一些简化函数,例如 convert_float4()。所以乍一看,我认为它会在 GPU 上运行得更快。但是,它的运行速度要慢得多(在使用高通 GPU 的 Nexus 4 和 5 上)。我认为这个例子很有代表性,因为在实现中,算法需要访问当前像素附近的像素。这种操作在许多图像处理算法中很常见。如果像 2D 卷积这样的实现不能在 GPU 中变得更快,我怀疑还有很多其他算法也会遇到同样的问题。如果您能确定问题出在哪里并提出一些使此类算法更快的方法,我们将不胜感激。
更一般的问题是,鉴于我展示的测试结果,我想问一下人们应该遵循什么样的标准才能获得更高的性能并尽可能避免性能下降。毕竟,性能目标是 Renderscript 的第二重要目标,我认为 RS 的可移植性非常好。
谢谢!
最佳答案
这个问题实际上有两个答案。
1:不要相信有关 GPU 的炒作。对于某些工作负载,它们更快。但是,对于许多工作负载,差异很小或为负。您至少有 2 种不同的处理器类型,不必担心使用哪一种,只需担心性能是否符合您的要求。
2:对于性能调整,我会真正关注算法并避免缓慢的操作。示例:
当 float 提供足够的精度时,首选 float 而不是 double。
当您不需要符合 IEEE-754 标准时使用 RS_FP_RELAXED
比起除法更喜欢乘法
在精度足够的地方使用 native_*(例如:native_powr)代替全精度例程
使用 rsGetElementAt_* 而不是 rsSample 或 rsGetElementAt。类型化版本的 get 比一般的 get 更快,并且在许多情况下比 rsSample 快得多。
从脚本全局变量加载通常比从 rs_allocation 加载更快。优先使用全局内核常量。
3:目前 Nexus (4,5,7v2) GPU 路径上的全局负载存在一些性能问题。这些将通过更新得到改进。
关于android - 为什么那些 Google 图像处理示例 Renderscript 在 Nexus 5 的 GPU 上运行速度较慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20382860/