0

Android アプリにいくつかのコードがあり、アプリをプロファイリングするときに、ほとんどの時間を占めるコードがあります。最適化を試みましたが、まだ CPU 時間のほとんどを占めています。どうすればこれをスピードアップできるかについて誰かがアイデアを持っているかどうか疑問に思っています。これは、使用しているコードの要約バージョンです。

入力:
d は float 配列
a は float 配列
e は float 配列

出力:
out は 3 つの float の配列です

コード:

float [] c=new float[3];
float [] b=new float[3];
float [] out=new float[3];

c[0] = a[0] - d[0 * 4 + 3];
c[1] = a[1] - d[1 * 4 + 3];
c[2] = a[2] - d[2 * 4 + 3];

b[0] = c[0]*d[0 * 4 + 0] + c[1]*d[1 * 4 + 0] + c[2]*d[2 * 4 + 0];
b[1] = c[0]*d[0 * 4 + 1] + c[1]*d[1 * 4 + 1] + c[2]*d[2 * 4 + 1];
b[2] = c[0]*d[0 * 4 + 2] + c[1]*d[1 * 4 + 2] + c[2]*d[2 * 4 + 2];           

out[0] = b[0] * e[0 * 4 + 0] + b[1] * e[0 * 4 + 1] + b[2] * e[0 * 4 + 2] + e[0 * 4 + 3];
out[1] = b[0] * e[1 * 4 + 0] + b[1] * e[1 * 4 + 1] + b[2] * e[1 * 4 + 2] + e[1 * 4 + 3];
out[2] = b[0] * e[2 * 4 + 0] + b[1] * e[2 * 4 + 1] + b[2] * e[2 * 4 + 2] + e[2 * 4 + 3];

3D モデル アニメーションの頂点変換に興味がある人向け。'out' は変換された頂点、'a' は元の頂点です。残りの配列はスケルトン ジョイント情報です。

4

4 に答える 4

1

コードの残りの部分は何をしますか? これは小さなコードのように見えるため、非常に高速に実行されるはずです。本当にパフォーマンスの問題がありますか? それとも、プログラムが CPU をまったく消費しないようにしようとしていますか?

とはいえ、単純にこれらすべての些細な算術演算を事前計算することもできます。

c[0] = a[0] - d[3];
c[1] = a[1] - d[7];
c[2] = a[2] - d[11];

にアクセスする方法がわかりませんが、d[3]は3 つの要素の配列であるはずです。d[7]d[11]d

于 2012-10-29T20:11:14.913 に答える
0

すべてのコンパイル時の定数は、コンパイラによって定数で折りたたまれます(しなければなりません)。できることは、とにかく配列として使用していない一時配列を削除することだけです。私はこのように試しました:

public float[]  transform2(float[] a, float[] d, float[] e)
{
    float c0,c1,c2;
    float b0,b1,b2;
    float [] out=new float[3];

    c0 = a[0] - d[0 * 4 + 3];
    c1 = a[1] - d[1 * 4 + 3];
    c2 = a[2] - d[2 * 4 + 3];

    b0 = c0*d[0 * 4 + 0] + c1*d[1 * 4 + 0] + c2*d[2 * 4 + 0];
    b1 = c0*d[0 * 4 + 1] + c1*d[1 * 4 + 1] + c2*d[2 * 4 + 1];
    b2 = c0*d[0 * 4 + 2] + c1*d[1 * 4 + 2] + c2*d[2 * 4 + 2];           

    out[0] = b0 * e[0 * 4 + 0] + b1 * e[0 * 4 + 1] + b2 * e[0 * 4 + 2] + e[0 * 4 + 3];
    out[1] = b0 * e[1 * 4 + 0] + b1 * e[1 * 4 + 1] + b2 * e[1 * 4 + 2] + e[1 * 4 + 3];
    out[2] = b0 * e[2 * 4 + 0] + b1 * e[2 * 4 + 1] + b2 * e[2 * 4 + 2] + e[2 * 4 + 3];

    return out;
}

あなたのコードは、反復を実行するのに 35665 ミリ秒かかりました10000000000Ltransform2()20077ms かかったので、2 倍以下の速さです。どちらのメソッドも最初にウォームアップされ、a[]、d[]、および e[] にはランダムな float が含まれていました。

out外部で保存できる場合は、メソッド内でパラメーターを割り当てる代わりにパラメーターを作成することで改善できるのではないかと思いましたoutが、呼び出しコードでは不可能な場合があります。しかし、それを 4 番目のパラメーターとして追加すると、桁違いに悪化しました。一部の HotSpot 最適化が元に戻されたに違いありません。ただし、Android を使用しているため、可能であればこれを検討してください。

それは多くの繰り返しです...

于 2012-10-29T23:39:06.633 に答える
0

これでできることはあまりありません..すべての操作は割り当てと数学であり、それらを実装しません。さらに、これらの操作はすでに非常に高速です...Javaは乗算する前にこれらの数値をすべて格納する必要があるため、何らかのforループでこれを行う方がメモリ効率が高くなります。動的に行う方が効率的です。

于 2012-10-29T20:11:29.313 に答える
0

ゼロによる1つの乗算はゼロに単純化してから加算を削除できますが、コンパイラまたはホットスポットがすでにそれを行っていると確信しています。

再計算を防ぐために、結果をメモしてみることができます。

また、JCudaを使用して、この種の数学を GPU にオフロードすることもできますが、これが Android でサポートされているかどうかはわかりません。

于 2012-10-29T20:11:50.187 に答える