10

Microsoft Accelerator が機能するのと同様に、プログラマーが簡単に使用できる API を作成する目的で、最近 RenderScript を使用しています。

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

これは、2 つの基本的な配列を作成し、それらに値を入力して、それらを 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);
 }

しかし、これには 2 つの問題があります。最初の 1 つは RenderScript の非同期性です。これは、Java レイヤーが値を要求したときに、スクリプトがまだ操作を実行していないか、既に実行しており、出力の値を破棄することを意味します。そして次の仕事を始めました。また、RenderScript のデバッグ可視性が低いため、判断する方法がありません。

もう 1 つの問題は、あまり効率的ではないことです。コードは常に RenderScript 関数を呼び出して 2 つの数値を加算しています。理想的には、配列を RenderScript に渡し、それを構造体に格納して、操作全体を多数ではなく 1 回のスクリプト呼び出しで実行したいと考えています。しかし、それを取り戻すには、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 (ここにいくつかの引数) を使用できます。

うまくいけば、これが少なくとも少しは役に立ちます。

于 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 に表示できます。

2 番目の質問は、intAdd() 関数をリコールせずに実装することです。上記のコードが答えです。メソッドが完了するまで、Java の int 配列の任意の部分にアクセスできます ( root() 関数とは異なります)。

これが誰かを助けることを願っています:)

于 2014-08-17T18:55:18.800 に答える