Android - RenderScript - SDK 21 中的性能下降

Android - RenderScript - Performance drop in SDK 21

我正在开发一个需要复杂的 Photoshop 类型混合效果的项目。我正在使用自定义 RenderScript 脚本来解决这个问题。

我一直在 Samsung Galaxy S4 设备 运行ning Kitkat 上测试它,一切都运行得很好而且非常快。

然后我尝试在 Nexus 5 运行ning Lollipop 上测试它,我注意到性能突然下降.

我开始对代码中的各个部分进行计时,以查看哪些部分速度变慢,并得出以下结论:

Allocation.createFromBitmap
- Runtime on Kitkat - ~5-10 millisec
- Runtime on Lollipop - ~100-150 millisec

mRenderScript.destory()
- Runtime on Kitkat - ~1-3 millisec
- Runtime on Lollipop - ~60-100 millisec

我很好奇为什么在本应更强大的设备上创建 Allocation 对象并销毁 RenderScript 对象时性能会突然下降,而在 OS 哪个应该更高级。

我可以针对 API 21 OS 做些什么来使这些方法 运行 更快吗?

有没有人遇到过这个问题或者可以重现它?

我应该注意到脚本的实际 运行ning(即 ScriptC.forEach 方法)运行 在两个设备上都非常快/OS .另外,我使用的是原生 RenderScript APIs 而不是任何支持库。

如有任何意见,我们将不胜感激。

编辑:

我在 Allocation.java

的 Github 中复制了 Androids Lollipop-release 源代码中的相关行
static public Allocation createFromBitmap(RenderScript rs, Bitmap b) {
        if (rs.getApplicationContext().getApplicationInfo().targetSdkVersion >= 18) {
            return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
                                    USAGE_SHARED | USAGE_SCRIPT | USAGE_GRAPHICS_TEXTURE);
        }
        return createFromBitmap(rs, b, MipmapControl.MIPMAP_NONE,
                                USAGE_GRAPHICS_TEXTURE);
    }

注意当目标 SDK 高于 17 时,Allocation 是如何默认使用 USAGE_SHARED 标志创建的。可能是这些额外的标志导致了问题吗?我应该改用 USAGE_GRAPHICS_TEXTURE 标志吗?

编辑 2

按照 R. Jason Sam 的建议,当 Nexus 5 连接到我的计算机时,我 运行 以下脚本:

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

在此之后,运行上述函数的时间明显加快(分别为 ~30-40 毫秒和 20-50 毫秒)。仍然不如棒棒糖之前的设备那么快,但在可接受的性能范围内 运行ge.

我对这个解决方案的唯一问题是,除非我不明白,否则不能被视为解决方案,因为它需要我在每个有问题的设备上调用这个脚本,然后再 运行 应用程序就可以了。

我可以在我的代码中做些什么来模拟这个 adb 调用吗?

最终编辑

好的,问题似乎源于我每次调用使用 RenderScript 执行混合效果的函数时都创建了一个新的 RenderScript 对象。

我做了一些代码重构,现在,我不再在每次调用 effect 方法时创建一个新的 RenderScript 对象,而是每次都重复使用相同的对象。在 Lollipop 设备上创建 RenderScript 对象的第一次创建仍然需要更长的时间,但现在问题得到缓解,因为我在多个方法调用中继续重复使用相同的对象。

我会将其添加为答案。

在 Api 18 (USAGE_SHARED) 中添加了一个分配类型。如果您强制 Renderscript 复制位图后备内存(而不是就地使用它),这可能会导致差异。

 Allocation tmpOut = Allocation.createFromBitmap(mRenderContext, result, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SHARED);

问题似乎源于我每次调用使用 RenderScript.

执行混合效果的函数时都在创建一个新的 RenderScript 对象

我做了一些代码重构,现在,我不再在每次调用 effect 方法时都创建一个新的 RenderScript 对象,而是每次都重复使用同一个对象。 RenderScript 对象的第一次创建在 Lollipop 设备上创建仍然需要更长的时间,但现在问题得到缓解,因为我在多个方法调用中继续重复使用相同的对象。

一旦我确定我不再需要它以确保没有内存泄漏,我一定会在共享 RenderScript 对象上调用 destory()

根据 this post,重用 RenderScript 对象而不是每次创建一个新对象似乎是公平的做法,但我很高兴听到来自其他人关于他们在此事上的经验。遗憾的是,网上没有太多关于此主题的文档,但到目前为止,一切似乎都在多个设备/OS 上运行良好。