Как передать значения массива в и из Android RenderScript с помощью Allocations

Недавно я работал с RenderScript с целью создания API, который программист может использовать с легкостью, подобно тому, как работает Microsoft Accelerator.

Проблема, с которой я сейчас сталкиваюсь, поскольку я хочу передать значения на и из уровня RenderScript, и все работает максимально эффективно, это выдержка из моего исходного кода:

int[] A = new int[10]; int[] B = new int[10]; for (int i = 0; i < 10; i++) { A[i] = 2; B[i] = i; } intAdd(A, B); 

Это просто создает два основных массива и заполняет их значениями и вызывает функции, которые будут отправлять их в RenderScript.

  private void intAdd(int[] A, int[] B) { RenderScript rs = RenderScript.create(this); ScriptC_rsintadd intaddscript = new ScriptC_rsintadd(rs, getResources(), R.raw.rsintadd); mScript = intaddscript; for(int i = 0; i < A.length; i++) { setNewValues(mScript, A[i], B[i]); intaddscript.invoke_intAdd(); int C = getResult(mScript); notifyUser.append(" " + C); } } public void setNewValues(Script script, int A, int B) { mScript.set_numberA(A); mScript.set_numberB(B); } public int getResult(Script script) { int C = mScript.get_numberC(); return C; } 

Это отправит пару значений в следующий код RenderScript:

 int numberA; int numberB; int numberC; void intAdd() { /*Add the two together*/ numberC = numberA + numberB; /*Send their values to the logcat*/ rsDebug("Current Value", numberC); } 

Но есть две проблемы с этим: первый асинхронный характер RenderScript означает, что когда уровень Java запрашивает значение, сценарий либо еще не выполнил операцию, либо уже сделал это, уничтожил значение вывода И начал на следующем. И благодаря низкой отладочной видимости RenderScript нет возможности рассказать.

Другая проблема заключается в том, что она не очень эффективна, код постоянно вызывает функцию RenderScript для добавления двух чисел вместе. В идеале я хотел бы передать массив в RenderScript и сохранить его в структуре и выполнить всю операцию в одном вызове скрипта, а не во многих. Но для того, чтобы вернуть его, я считаю, что мне нужно будет использовать функцию rsSendtoClient, но я не нашел никаких материалов о том, как ее использовать. И, желательно, я бы хотел использовать стратегию rsForEach, но снова информация пугает.

Если у кого-нибудь есть идеи, я буду очень благодарен. Благодарю.

Будет Скотт-Джексон

Я не уверен, что это поможет вам в этот момент, но так как я знаю, насколько боль может работать через RenderScript, вот помощь, которую я могу предложить. Чтобы использовать функцию rsSendToClient, вам необходимо указать экземпляр RenderScript, который вы создали, куда отправлять сообщения. Это достигается чем-то вроде:

 private void intAdd(int[] A, int[] B) { RenderScript rs = RenderScript.create(this); MySubclassedRSMessageHandler handler = new MySubclassedRSMessageHandler(); rs.setMessageHandler(handler); ScriptC_rsintadd intaddscript = new ScriptC_rsintadd(rs, getResources(), R.raw.rsintadd); mScript = intaddscript; for(int i = 0; i < A.length; i++) { setNewValues(mScript, A[i], B[i]); intaddscript.invoke_intAdd(); int C = getResult(mScript); notifyUser.append(" " + C); } } 

Необходимо будет подклассифицировать RenderScript.RSMessageHandler и переопределить метод run (). См. http://developer.android.com/reference/android/renderscript/RenderScript.RSMessageHandler.html, если вы уже не знаете. В принципе, нет никакого способа обойти асинхронную природу, которую я считаю обоюдоострым мечом.

Что касается неэффективности, я бы подумал о создании экземпляра RenderScript, оставьте его в рабочем состоянии (вы можете приостановить его, когда это не нужно, останется в памяти, но остановите потоки, поэтому не прибегайте к стоимости строительства каждый раз, когда вы вызываете функцию). Отсюда вы можете иметь свои структуры, а затем использовать invoke_myFunction (некоторые аргументы здесь) из отраженного уровня Java.

Надеюсь, это поможет хотя бы немного.

У меня такая же проблема. Проблема с вашей программой заключается в том, что она не знает, когда должна работать функция add в файле rs, попробуйте это, она должна работать

 public void setNewValues(Script script, int A, int B) { mScript.set_numberA(A); mScript.set_numberB(B); mscript.invoke_intAdd(); } 

У меня была такая же проблема с тобой. Я думаю, что функция rsSendtoClient не полезна и создает много ошибок. Вместо этого, используя указатель и выделяя его, память для возврата результата вам намного проще.

Я рекомендую решение вашей проблемы следующим образом:

В rsintadd.rs используйте этот фрагмент:

 int32_t *a; int32_t *b; int32_t *c; void intAdd() { for(int i = 0; i<10;i++){ c[i] = a[i] + b[i]; } 

В вашем коде JAVA используйте этот фрагмент:

  int[] B = new int[10]; int[] A = new int[10]; for (int i = 0; i < 10; i++) { A[i] = 2; B[i] = 1; } // provide memory for b using data in B Allocation b = Allocation.createSized(rs, Element.I32(rs), B.length); b.copyFrom(B); inv.bind_b(b); // provide memory for a using data in A Allocation a = Allocation.createSized(rs, Element.I32(rs), A.length); a.copyFrom(A); inv.bind_a(a); // create blank memory for c inv.bind_c(Allocation.createSized(rs, Element.I32(rs), 10)); // call intAdd function inv.invoke_intAdd(); // get result int[] C = new int[10]; inv.get_c().copyTo(C); for (int i = 0; i < C.length; i++) { System.out.println(C[i]); } 

И это ваш результат на Logcat:

Результат C

Ваш первый вопрос касается асинхронности, вы можете использовать поток для ожидания результата. В этом примере функция достаточно быстрая и мгновенно дает вывод в массив C, поэтому результат может отображаться на logcat.

Второй вопрос – реализовать функцию intAdd (), не напомнив об этом. Вышеприведенный код является ответом. Вы можете получить доступ к любой части массива int в Java до тех пор, пока метод не будет выполнен (отличная от функции root ()).

Надеюсь, это может помочь кому-то 🙂