强制默认CPU实现时,RenderScript加速10倍

时间:2016-05-14 15:23:24

标签: android performance cpu renderscript

我在RenderScript中实现了一个CNN,在previous question中描述了它产生了这个。基本上,在运行时

adb shell setprop debug.rs.default-CPU-driver 1

Nvidia Shield和Nexus 7都有10倍的加速。平均计算时间从大约50ms到5ms,测试应用程序从大约50fps到130或更高。有两种卷积算法:

(1)移动内核
 (2)来自RenderScriptIntrinsicsBLAS的im2col和GEMM。

两者都有类似的加速。问题是:为什么会发生这种情况,并且可以通过可预测的方式从代码中实例化这种效果?有关这方面的详细信息吗?

编辑:

根据下面的建议,我验证了finish()和copyTo()的使用,这里是程序的细分。报告的加速是在调用copyTo()但没有finish()之后。取消注释finish()会增加大约1ms的时间。

double forwardTime = 0;
long t = System.currentTimeMillis();
//double t = SystemClock.elapsedRealtime(); // makes no difference
for (Layer a : layers) {
    blob = a.forward(blob);
}
mRS.finish();   // adds about 1ms to measured time 

blob.copyTo(outbuf);
forwardTime = System.currentTimeMillis() - t;​

也许这是无关的,但在NVIDIA Shield上,我在启动时收到一条错误消息,当使用adb shell setprop debug.rs.default-CPU-driver 1

运行时它会消失
E/Renderscript: rsAssert failed: 0, in vendor/nvidia/tegra/compute/rs/driver/nv/rsdNvBcc.cpp

我现在使用buildToolsVersion" 23.0.2"将compileSdkVersion,minSdkVersion和targetSdkVersion设置为23。平板电脑自动更新到最新的Android版本。我不确定我需要设置的最小目标,并且仍然可以使用ScriptIntrinsicsBLAS。

我在所有脚本中使用#pragma rs_fp_relaxed。 Allocations都使用默认标志 This question有类似的情况,但事实证明OP在每一轮计算中都在创建新的Script对象。我什么都不做,所有的脚本和分配都是在初始时创建的。

2 个答案:

答案 0 :(得分:0)

原帖有mRS.finish()注释掉了。我想知道这是不是这样。

要正确地对RenderScript进行基准测试,我们应该等待挂起的异步操作完成。通常有两种方法:

  1. 使用RenderScript.finish()。使用debug.rs.default-CPU-driver 1时效果很好。它也适用于大多数GPU驱动程序。但是,某些GPU驱动程序确实将其视为NOOP。
  2. 使用Allocation.copyTo()或其他类似API访问分配数据,最好是最终输出分配。这实际上是一个技巧,但它适用于所有设备。请注意,copyTo操作本身可能需要一些时间,并确保考虑到这一点。
  3. 这里的5ms似乎很可疑,它可能是真实的,取决于实际的算法。但是,当你添加finish()或copyTo()时仍然需要仔细检查。

答案 1 :(得分:0)

确实很奇怪。事实上,你在两个设备上得到相同的结果,并且有两个非常不同的转换层实现,这表明基准测试或时序本身还有其他一些事情,而不是与CPU / GPU执行的差异,因为事情是很少有结论。

我建议验证copyTo()的输出始终是相同的。设置一个logcat输出,例如,从每个层的输出分配返回的float数组中的第一个(和最后一个!)10个值,以确保所有实现和执行模式真正正确地处理每个层的数据。< / p>

根据您的设置,我之前提到的数据复制开销可能会压缩计算时间本身,而您所看到的只是一个不幸的影响,因为它可能从一个地方或另一个地方复制数据需要更多或更少的时间。尝试增加conv内核大小或计数(使用虚拟/随机值,仅用于测试),使计算更加复杂,从而抵消计算与数据加载时间之间的平衡,并查看它对结果的影响。

如果所有其他方法都失败了,那可能只是因为某些原因GPU真的需要更长时间,尽管很难找到原因。要检查的内容......您使用的数据类型和大小是多少?如何将数据加载/写入分配?您是否已经使用#pragma rs_fp_relaxed来设置浮点精度?您为分配用法设置了哪些标志(例如Allocation.USAGE_SCRIPT | Allocation.USAGE_GRAPHICS_TEXTURE)?

关于你的上一个问题,遗憾的是,关于特定优化问题的详细RS文档仍然非常缺乏......我想在这里询问SO仍然是目前可用的最佳资源之一:)