3

アルゴリズムの一部を C から ARM アセンブラー (NEON 命令を使用) に変換しましたが、元の C コードよりも 2 倍遅くなりました。どうすればパフォーマンスを向上させることができますか?

ターゲットは ARM Cortex-A9 です。

このアルゴリズムは、配列から 64 ビット値を読み取ります。この値から 1 バイトが抽出され、別のテーブルのルックアップ値として使用されます。この部分は約 10 回実行され、結果の各テーブル値が他の値と XOR 演算され、最終結果が別の配列に書き込まれます。

このようなもの:

result[i] = T0[ GetByte0( a[i1] ) ] ^ T1[ GetByte1( a[i2] ) ] ^ ... ^ T10[ (...) ];

私のアプローチでは、配列「a」全体を Neon Registers にロードしてから、右のバイトをアームレジスタに移動し、オフセットを計算してから、テーブルから値をロードします。

vldm.64 r0, {d0-d7}         //Load 8x64Bit from the input array

vmov.u8 r12, d0[0]          //Mov the first Byte from d0 into r12
add r12, r2, r12, asl #3    // r12 = base_adress + r12 << 3
vldr.64 d8, [r12]           // d8 = mem[r12]
.
.
.
veor d8, d8, d9             // d8 = d8 ^ d9
veor d8, d8, d10            // d8 = d8 ^d10      ...ect.

ここで、r2 はルックアップ テーブルのベース アドレスを保持します。

adress = Table_adress + (8* value_fromByte);

このステップ (最初のロードを除く) は 100 回ほど実行されます。なぜこれはとても遅いのですか?

また、 「vld」「vldr」、および「vldm」の違いは何ですか- そしてどれが最速です。Neon レジスタ内でのみオフセット計算を実行するにはどうすればよいですか? ありがとうございました。

4

4 に答える 4

3

Neon は、VTBL 命令の制限 (私の記憶が正しければ 32 バイト) を超えるルックアップを処理する能力があまりありません。
そもそもルックアップ テーブルはどのように作成されるのでしょうか。計算だけの場合は、ルックアップに頼るのではなく Neon に計算させてください。この方法ではるかに高速になります。

于 2012-02-24T03:10:51.440 に答える
2

使用しないでください

vmov.u8 r12, d0[0]

NEON レジスタから ARM レジスタにデータを移動することは、あなたができる最悪のことです。

たぶん、VTBL命令が表示されるはずです! バイト範囲 0..255 は何ですか?

于 2012-02-23T14:40:32.067 に答える
1

あなたが試すことができるかもしれません

ldrb     r12, [r0], #1
add      r3, r2, r12, asl #3
vld1.64  {d0}, [r3]

ldrb     r12, [r0], #1
add      r3, r2, r12, asl #3
vld1.64  {d1}, [r3]
veor     d0, d0, d1         // d8 = d8 ^ d1

ldrb     r12, [r0], #1
add      r3, r2, r12, asl #3
vld1.64  {d1}, [r3]
veor     d0, d0, d1         // d8 = d8 ^ d1

...

それは最善の解決策ではありません。その後、命令を並べ替えることでパフォーマンスを向上させることができます。

于 2012-02-23T15:32:13.377 に答える
0

NEON「組み込み関数」で試してみてください。基本的に、これらは NEON 命令にコンパイルされる C 関数です。コンパイラは引き続きすべての命令スケジューリングを行うことができ、他の退屈なもの (データの移動) は無料で入手できます。

常に完全に機能するとは限りませんが、手作業でコーディングするよりはましかもしれません。

を探しarm_neon.hます。

于 2012-02-24T11:29:24.750 に答える