【问题标题】:Renderscript fails on GPU enabled driver if USAGE_SHARED如果 USAGE_SHARED,Renderscript 在启用 GPU 的驱动程序上失败
【发布时间】:2018-11-06 00:30:01
【问题描述】:

我们正在使用渲染脚本进行音频 dsp 处理。对于我们的用例来说,它很简单并且显着提高了性能。但是,在启用了 GPU 执行的自定义驱动程序的设备上,我们遇到了 USAGE_SHARED 的一个恼人问题。

您可能知道,USAGE_SHARED 标志使渲染脚本分配重用给定的内存,而无需创建它的副本。因此,它不仅可以节省内存,在我们的例子中,还可以将性能提高到所需的水平。

以下带有USAGE_SHARED 的代码在默认渲染脚本驱动程序(libRSDriver.so) 上运行良好。使用自定义驱动程序 (libRSDriver_adreno.so) USAGE_SHARED 不会重用给定的内存和数据。

这是使用USAGE_SHARED并调用renderscript内核的代码

void process(float* in1, float* in2, float* out, size_t size) {
  sp<RS> rs = new RS();
  rs->init(app_cache_dir);

  sp<const Element> e = Element::F32(rs);
  sp<const Type> t = Type::create(rs, e, size, 0, 0);

  sp<Allocation> in1Alloc = Allocation::createTyped(
                rs, t,
                RS_ALLOCATION_MIPMAP_NONE, 
                RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
                in1);

  sp<Allocation> in2Alloc = Allocation::createTyped(
                rs, t,
                RS_ALLOCATION_MIPMAP_NONE, 
                RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
                in2);

  sp<Allocation> outAlloc = Allocation::createTyped(
                rs, t,
                RS_ALLOCATION_MIPMAP_NONE, 
                RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED,
                out);

  ScriptC_x* rsX = new ScriptC_x(rs);
  rsX->set_in1Alloc(in1Alloc);
  rsX->set_in2Alloc(in2Alloc);
  rsX->set_size(size);

  rsX->forEach_compute(in1Alloc, outAlloc);
}

注意:文档中没有提到Allocation::createTyped() 的这种变体,但代码rsCppStructs.h 有它。这是允许提供支持指针并尊重USAGE_SHARED 标志的分配工厂方法。这是它的声明方式:

/**
 * Creates an Allocation for use by scripts with a given Type and a backing pointer. For use
 * with RS_ALLOCATION_USAGE_SHARED.
 * @param[in] rs Context to which the Allocation will belong
 * @param[in] type Type of the Allocation
 * @param[in] mipmaps desired mipmap behavior for the Allocation
 * @param[in] usage usage for the Allocation
 * @param[in] pointer existing backing store to use for this Allocation if possible
 * @return new Allocation
 */
static sp<Allocation> createTyped(
            const sp<RS>& rs, const sp<const Type>& type,
            RsAllocationMipmapControl mipmaps, 
            uint32_t usage, 
            void * pointer);

这是渲染脚本内核

rs_allocation in1Alloc, in2Alloc;
uint32_t size;

// JUST AN EXAMPLE KERNEL
// Not using reduction kernel since it is only available in later API levels.
// Not sure if support library helps here. Anyways, unrelated to the current problem

float compute(float ignored, uint32_t x) {
  float result = 0.0f;
  for (uint32_t i=0; i<size; i++) {
    result += rsGetElementAt_float(in1Alloc, x) * rsGetElementAt_float(in2Alloc, size-i-1); // just an example computation
  }

  return result;
}

如前所述,out 没有任何计算结果。 syncAll(RS_ALLOCATION_USAGE_SHARED) 也没有帮助。

以下工作虽然(但慢得多)

void process(float* in1, float* in2, float* out, size_t size) {
  sp<RS> rs = new RS();
  rs->init(app_cache_dir);

  sp<const Element> e = Element::F32(rs);
  sp<const Type> t = Type::create(rs, e, size, 0, 0);

  sp<Allocation> in1Alloc = Allocation::createTyped(rs, t);
  in1Alloc->copy1DFrom(in1);

  sp<Allocation> in2Alloc = Allocation::createTyped(rs, t);
  in2Alloc->copy1DFrom(in2);

  sp<Allocation> outAlloc = Allocation::createTyped(rs, t);

  ScriptC_x* rsX = new ScriptC_x(rs);
  rsX->set_in1Alloc(in1Alloc);
  rsX->set_in2Alloc(in2Alloc);
  rsX->set_size(size);

  rsX->forEach_compute(in1Alloc, outAlloc);
  outAlloc->copy1DTo(out);
}

复制使其工作,但在我们的测试中,来回复制会显着降低性能。

如果我们通过debug.rs.default-CPU-driver 系统属性关闭 GPU 执行,我们可以看到自定义驱动程序运行良好,具有所需的性能。

将分配给渲染脚本的内存对齐到 16、32、.. 或 1024 等无助于使自定义驱动程序尊重 USAGE_SHARED。

问题

那么,我们的问题是:如何让这个内核在使用支持 GPU 执行的自定义渲染脚本驱动程序的设备上工作?

【问题讨论】:

  • 您是否尝试过添加 RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE?
  • 会尝试的。但我处理的不是图形,而是音频信号。 RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE 是否相关?
  • 使用 RS_ALLOCATION_USAGE_GRAPHICS_TEXTURE 检查。结果相同。

标签: android performance signal-processing renderscript android-renderscript


【解决方案1】:

即使您使用 USAGE_SHARED,您也需要拥有该副本。

USAGE_SHARED 只是给驱动程序的一个提示,它不必使用它。

如果驱动程序确实共享内存,则副本将被忽略并且性能将相同。

【讨论】:

  • 根据我们的实验,我认为您是对的。我接受了答案(你会在一天内得到赏金)。我们还可以得出的结论是,在我们的例子中,性能不受 USAGE_SHARED 的影响,有/没有副本,这与问题中所感知的不同。但是,目前尚不清楚为什么启用 GPU 的驱动程序的性能很差。默认驱动程序比自定义驱动程序快约 4 倍!我真的希望有一种方法可以在运行时恢复为默认驱动程序。
  • 您能否分享更多关于您的内核/启动参数以及您如何测量时序的信息?
  • 您可以在 RS::init() 中使用 RS_INIT_LOW_LATENCY 来强制使用默认的 CPU 驱动程序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-21
  • 2012-11-17
  • 1970-01-01
  • 1970-01-01
  • 2017-07-04
  • 2017-03-24
  • 1970-01-01
相关资源
最近更新 更多