10

我最近一直在使用 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 策略,但信息又是可怕的。

如果有人有任何想法,我将不胜感激。谢谢。

将斯科特-杰克逊

4

3 回答 3

2

我有同样的问题。您的程序的问题是不知道 rs 文件中的 add 函数应该何时运行,试试这个它应该可以工作

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

}
于 2012-05-30T11:54:48.440 回答
2

我不确定这是否会对您有所帮助,但由于我知道通过 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 实例,让它继续运行(您可以在不需要时暂停它,将保留在内存中但停止线程,因此每次调用函数时都不会产生构建成本)。从这里您可以拥有您的结构,然后从反射的 Java 层使用 invoke_myFunction(some arguments here)。

希望这至少有一点帮助。

于 2012-04-13T06:36:52.233 回答
0

我和你有同样的问题。我认为 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() 函数而不回忆它。上面的代码就是答案。在方法完成之前,您可以访问 Java 中 int 数组的任何部分(不同于 root() 函数)。

希望这可以帮助某人:)

于 2014-08-17T18:55:18.800 回答