2012-02-23 45 views
3

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

対象はARM Cortex-A9です。

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

何か:

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

私のアプローチでは、私は、全体の配列「」ネオンレジスタで、その後、腕レジスタの右バイトを動かし、オフセットを計算し、その後から値を読み込むを読み込みますテーブル:

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"との違いは何ですか。 ネオンレジスタ内でのみオフセット計算を実行するにはどうすればよいですか? ありがとうございます。

+0

私はあなたのCコードが記述と一致するとは思わない。 Cは同じ単語の複数のバイトを排他的論理和演算していますが、各バイトは次のバイトを索引付けするために使用されます。明確に表示できない場合は、コードを最適化することはできません。 – phkahler

+0

はい、あなたは正しいです。私はそれを編集した。それはいつも別の言葉です。 – HectorLector

答えて

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 

... 

を試すことができますように。その後、命令を並べ替えることでパフォーマンスを向上させることができます。

+0

はい、並べ替えが最後の部分になります。私はldrb命令でこれを試していますが、.quad値からバイトをロードできないようです。私はこのようにアセンブラに私のルックアップテーブルを定義します。 .GLOBAL T0 T0: .quad 0xc6a597f4a5f432c6 .quad 0xf884eb9784976ff8 が、LDRBのr1が、t0は失敗します。 なぜ "vldr.64"の代わりに "vld1.64"を使用する必要がありますか? – HectorLector

+1

これは、ルックアップ値が64ビットであるため、おそらく実際のルックアップを行う唯一の方法です。しかし、ベア・オペレーションの数は、クワッド・レジスタ上で行うことによって減らすことができる。 d0、d1、d2、d3に4つのルックアップ値をロードします。 veor q0、q0、q1を実行してveor d0、d0、d1を実行すると、2つの操作で4つの値のXORを実行します。 – Leo

+0

ldrbでは、Cバージョンよりも少し速くなっています。パフォーマンスやAR/NEONパイプラインの一般的な改善のために、コードの並べ替えに関するヒントはありますか? – HectorLector

2

は、ARMレジスタへNEONからデータを移動する

vmov.u8 r12, d0[0] 

を使用していないあなたが行うことができます最悪のことです。

VTBL命令が表示されるはずです。 あなたはバイト範囲0..255ですか?

+0

ありがとう、私はそれを変更しようとします。私が達成しようとしているのはこれです:私は2次元配列(8x8バイト)を持っています。私はすべての列から1つの異なるバイトが必要です。このバイト値は別のAray(64ビット)のインデックスです。だから私は正しいバイト値を取得する必要がありますテーブルで自分の値を検索し、XORすべての値を見つけた。私はこれが多かれ少なかれ理解できることを願っています。 – HectorLector

2

ネオンは、VTBL命令の制限(正しく覚えていれば32バイト)より大きいルックアップを扱うことはできません。
ルックアップテーブルはどのように作成されましたか?単なる計算であれば、ルックアップに頼る代わりにNeonに数学をさせてください。 これはずっと高速です。

+0

ルックアップテーブルは静的でハードコードされています。約2000の64ビット値。 – HectorLector

0

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

いつも完全には動作しませんが、手作業でコードを作成しようとするよりも良いかもしれません。

arm_neon.hを探します。

+1

ありがとう。私はそれを試みたが、それは十分に速くない。 – HectorLector

関連する問題