【问题标题】:Android renderscript never runs on the gpuAndroid 渲染脚本永远不会在 gpu 上运行
【发布时间】:2017-04-30 05:31:24
【问题描述】:

正如标题所说。

我有一个我想使用的并行图像创建/处理算法。这是一种 perlin 噪声实现。

// Logging is never used here
#pragma version(1)
#pragma rs java_package_name(my.package.name)
#pragma rs_fp_full

float sizeX, sizeY;
float ratio;

static float fbm(float2 coord)
{ ... }

uchar4 RS_KERNEL root(uint32_t x, uint32_t y)
{
float u = x / sizeX * ratio;
float v = y / sizeY;

float2 p = {u, v};

float res = fbm(p) * 2.0f;   // rs.: 8245 ms, fs: 8307 ms; fs 9842 ms on tablet

float4 color = {res, res, res, 1.0f};
//float4 color = {p.x, p.y, 0.0, 1.0};  // rs.: 96 ms

return rsPackColorTo8888(color);
}

作为比较,当我通过纹理四边形上的片段着色器在 gpu 上实现这个精确算法时,它的运行速度至少为 30 fps。

运行 RenderScript 的开销最多应为 100 毫秒,这是我通过返回 x 和 y 归一化坐标制作简单位图计算得出的。

这意味着如果它使用 gpu,它肯定不会变成 10 秒。

我使用 RenderScript 的代码:

// The non-support version gives at least an extra 25% performance boost
import android.renderscript.Allocation;
import android.renderscript.RenderScript;

public class RSNoise {

    private RenderScript renderScript;
    private ScriptC_noise noiseScript;

    private Allocation allOut;

    private Bitmap outBitmap;

    final int sizeX = 1536;
    final int sizeY = 2048;

    public RSNoise(Context context) {
        renderScript = RenderScript.create(context);

        outBitmap = Bitmap.createBitmap(sizeX, sizeY, Bitmap.Config.ARGB_8888);
        allOut = Allocation.createFromBitmap(renderScript, outBitmap, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_GRAPHICS_TEXTURE);

        noiseScript = new ScriptC_noise(renderScript);
    }

    // The render function is benchmarked only
    public Bitmap render() {
        noiseScript.set_sizeX((float) sizeX);
        noiseScript.set_sizeY((float) sizeY);
        noiseScript.set_ratio((float) sizeX / (float) sizeY);

        noiseScript.forEach_root(allOut);

        allOut.copyTo(outBitmap);

        return outBitmap;
    }
}

如果我将其更改为 FilterScript,从使用此帮助 (https://stackoverflow.com/a/14942723/4420543) 开始,在支持库的情况下,我的情况会差几百毫秒,在不支持的情况下会差大约两倍。精度不影响结果。

我还检查了有关 stackoverflow 的每个问题,但其中大多数都已过时,我还尝试使用 nexus 5(7.1.1 操作系统版本)以及其他几个新设备,但问题仍然存在。

那么,RenderScript 什么时候在 GPU 上运行?如果有人能给我一个运行 GPU 的 RenderScript 的例子就足够了。

【问题讨论】:

  • 这是很久以前的事了。我无法解决这个问题,并且它与人们可能认为的 #pragma rs_fp_relaxed 无关。关键在于我无法用自定义线程复制的AsyncTask 的专长。只有官方示例在 GPU 上运行稳定。

标签: android gpgpu renderscript


【解决方案1】:

您可以尝试使用 rs_fp_relaxed 而不是 rs_fp_full 来运行它吗?

#pragma rs_fp_relaxed

rs_fp_full 将强制您的脚本在 CPU 上运行,因为大多数 GPU 不支持全精度浮点运算。

【讨论】:

  • 禁用此行的一个问题是噪声实现需要高(浮点)精度,如果设备仅在不支持 gpu 的情况下使用 cpu 会更好,而不是渲染一个 ' gpu 上的“坏”图片。
  • "rs_fp_relaxed" 并不意味着它是OpenGL“高精度”的低精度。
  • 这里我们讨论的是计算精度。 "rs_fp_relaxed" 仍然是 32 位浮点精度,它只是放宽了某些数学运算,例如 denorm。实际上 GL 着色器会在移动设备上做类似的事情。我建议您在测试设备上尝试一下,看看是否适合您。
【解决方案2】:

我同意你的猜测。

在 Nexux 7(2013,JellyBean 4.3)上,我分别编写了一个渲染脚本和一个过滤器脚本来计算著名的 Mandelbrot 集。 与执行相同操作的 OpenGL 片段着色器(全部使用 32 位浮点数)相比,脚本大约慢了 3 倍。我假设 OpenGL 使用渲染脚本(和 filterscript !)不使用的 GPU。

然后我将相机预览转换(NV21 格式 -> RGB)分别与渲染脚本、过滤器脚本和 ScriptIntrinsicYuvToRGB 进行了比较。 Here Intrinsic 比自己编写的脚本快 4 倍。 我再次看到渲染脚本和过滤脚本之间的性能没有差异。在这种情况下,我假设自己编写的脚本仅在 Intrinsic 使用 GPU 的情况下再次使用 CPU(也是?)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-29
    • 2015-04-17
    • 1970-01-01
    相关资源
    最近更新 更多