5

私は Android でいくつかのリアルタイム DSP アルゴリズムを作成する作業を行っているため、可能な限りすべてを最適化し、数学を最大限に軽量化するために、ARM をアセンブリで直接プログラムすることにしました。最初はあまり意味のない速度ベンチマークを取得していたので、パイプラインの危険性や二重発行機能などについて読み始めました。取得している数字のいくつかにまだ困惑しているので、誰かが私が取得した理由を明らかにしてくれることを期待してここに投稿しています. 特に、NEON が各操作を正確に 1 サイクルで実行すると主張しているにもかかわらず、異なるデータ型で計算を実行するのに異なる時間がかかる理由に興味があります。私の調査結果は次のとおりです。

私はベンチマークに非常に単純なループを使用しており、2,000,000 回の反復を実行しています。これが私の機能です:

hzrd_test:

    @use received argument an number of iterations in a loop
    mov r3 , r0

    @come up with some simple values
    mov r0, #1
    mov r1, #2

    @Initialize some NEON registers (Q0-Q11)
    vmov.32 d0, r0, r1
    vmov.32 d1, r0, r1
    vmov.32 d2, r0, r1

    ...

    vmov.32 d21, r0, r1
    vmov.32 d22, r0, r1
    vmov.32 d23, r0, r1

hzrd_loop:

    @do some math
    vadd.s32 q0, q0, q1
    vadd.s32 q1, q0, q1
    vadd.s32 q2, q0, q1
    vadd.s32 q3, q0, q1
    vadd.s32 q4, q0, q1
    vadd.s32 q5, q0, q1
    vadd.s32 q6, q0, q1
    vadd.s32 q7, q0, q1
    vadd.s32 q8, q0, q1
    vadd.s32 q9, q0,s q1
    vadd.s32 q10, q0, q1
    vadd.s32 q11, q0, q1

    @decrement loop counter, branch to loop again or return
    subs r3, r3, #1
    bne hzrd_loop

    @return
    mov r0, r3
    mov pc, lr

vector add ( vadd) および signed 32-bit int ( s32) として指定された計算操作とデータ型に注目してください。この操作は一定時間内に完了します (以下の結果表を参照)。この ARM Cortex-A8 ドキュメントと次のページによると、NEON のほとんどすべての基本的な算術演算は 1 サイクルで完了するはずですが、私が得ているものは次のとおりです。

vmul.f32 ~62ms
vmul.u32 ~125ms
vmul.s32 ~125ms

vadd.f32 ~63ms
vadd.u32 ~29ms
vadd.s32 ~30ms

上記のループ内のすべての操作とデータ型を単純に置き換えることで、それらを実行します。よりも 2 倍速く、よりvadd.u322 倍速い理由はありvadd.f32ますか?vmul.f32vmul.u32

乾杯!= )

4

2 に答える 2

6

うわー、あなたの結果は非常に正確です:

  • 32 ビット整数の Q 乗算は 4 サイクルかかりますが、float は 2 サイクルかかります。
  • 32 ビット整数の Q add は 1 サイクルかかりますが、float は 2 サイクルかかります。

素敵な実験。

すでにご存知かもしれませんが、 NEON のコーディングには注意が必要です。

  • NEONが重い仕事をしている間はARMでメモリにアクセスしないでください
  • VFP 命令と NEON 命令を混在させないでください。(共有のものを除く)
  • S レジスタにアクセスしないでください。
  • NEON レジスタから ARM レジスタに転送しないでください

上記のすべてが大きな問題を引き起こします。

幸運を!

PS : ほぼすべての新しいデバイスに A9 が搭載されているため、代わりに A9 を最適化します (サイクル タイミングがわずかに異なります)。また、ARM の A9 タイミング チャートは、はるかに読みやすくなっています。:-)

于 2011-11-08T21:21:45.443 に答える
4

パイプラインの問題が発生していると推測します (ドキュメント リンクが手元にないため)。FPU - 現在 VFPU と呼ばれているエラーのパイプラインの長さは、CPU がループの整数演算部分を実行する場合とは異なります。2 番目の算術演算は最初の演算に依存しているため、いずれかのパイプラインが停止し、表示されている違いが明らかになる可能性があります。

また、乗算は int の 1 サイクルの命令ではなく、2 番目の値の msb に応じて 2 ~ 5 サイクルであると考えています。それを確認するには、乗算数を大きくして開始し、サイズが大きくなると速度が低下するかどうかを確認します。

また、その可能性を排除するために、コードがすべて 1 つのキャッシュ ページに収まることも確認します。

物事が相互に依存している場合にも、あらゆる種類のパイプラインの停止が発生するため、上記のデュアル実行に関するセクションもチェックしてください。

于 2011-11-08T18:38:30.310 に答える