Вы можете использовать RS_INIT_LOW_LATENCY в RS :: init (), чтобы принудительно использовать драйвер ЦПУ по умолчанию.

пользуем Renderscript для обработки аудио DSP. Это просто и значительно повышает производительность для нашего варианта использования. Но мы сталкиваемся с раздражающей проблемойUSAGE_SHARED на устройствах, у которых есть пользовательский драйвер с включенным выполнением графического процессора.

Как ты можешь знать,USAGE_SHARED Флаг делает выделение Renderscript для повторного использования данной памяти, не создавая ее копию. Как следствие, это не только экономит память, в нашем случае повышает производительность до желаемого уровня.

Следующий код с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);

Это ядро ​​Renderscript

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);
}

Копирование заставляет его работать, но в нашем тестировании копирование туда и обратно значительно снижает производительность.

Если мы отключим выполнение GPU черезdebug.rs.default-CPU-driver Системное свойство, мы могли видеть, что пользовательский драйвер хорошо работает с желаемой производительностью.

Выравнивание памяти, выделенной для Renderscript в 16,32, .., или 1024 и т. Д., Не помогло заставить пользовательский драйвер уважать USAGE_SHARED.

Вопрос

Итак, наш вопрос заключается в следующем: как заставить это ядро ​​работать на устройствах, которые используют пользовательский драйвер Renderscript, который позволяет выполнять GPU?

Ответы на вопрос(1)

Ваш ответ на вопрос