2

NEONの12個のクワッドレジスタをロードする単純なasmコードがあり、ロード命令とともにペアワイズ加算命令を並列化しました(デュアル発行機能を利用するため)。ここでコードを確認しました:

http://pulsar.webshaker.net/ccc/sample-d3a7fe78

ご覧のとおり、コードは約 13 サイクルかかります。しかし、ボードにコードをロードすると、ロード命令はロードごとに 1 サイクル以上かかるようです。確認したところ、前述のように VPADAL は 1 サイクルかかりますが、VLD1 は 1 サイクル以上かかることがわかりました。何故ですか?

私は次の世話をしました:

  1. アドレスは 16 バイトでアラインされています。
  2. 説明書に位置合わせのヒントを提供しているvld1.64 {d0, d1} [r0,:128]!
  3. プリロード命令pld [r0, #192]をいくつかの場所で試してみましたが、実際に待ち時間を短縮するのではなく、サイクルを追加しているようです。

誰かが私が間違っていることを教えてもらえますか?なぜこの遅延が発生するのですか?

その他の詳細:

  • cortex-a8を参考に
  • arm-2009q1 クロス コンパイラ ツール チェーン
  • アセンブリでのコーディング
4

1 に答える 1

2

あなたのコードは、現在書かれているように、パイプライン ストールの完璧な嵐を引き起こしているため、予想よりもはるかに遅く実行されています。パイプライン化されたアーキテクチャを備えた最新の CPU では、理想的な条件下で命令を 1 サイクルで実行できます。理想的な条件は、命令がメモリを待機しておらず、レジスタ依存性がないことです。コードを書いた方法では、メモリからの読み取りの遅延を考慮しておらず、次の命令を読み取りの結果に依存させていません。これにより、最悪のパフォーマンスが発生します。また、ペアワイズ加算を複数のレジスタに蓄積している理由がわかりません。次のようなことを試してください:

    veor.u16 q12,q12,q12     @ clear accumulated sum
top_of_loop:
    vld1.u16 {q0,q1},[r0,:128]!
    vld1.u16 {q2,q3},[r0,:128]!
    vpadal.u16 q12,q0
    vpadal.u16 q12,q1
    vpadal.u16 q12,q2
    vpadal.u16 q12,q3
    vld1.u16 {q0,q1},[r0,:128]!
    vld1.u16 {q2,q3},[r0,:128]!
    vpadal.u16 q12,q0
    vpadal.u16 q12,q1
    vpadal.u16 q12,q2
    vpadal.u16 q12,q3
    subs r1,r1,#8
    bne top_of_loop

add を実行する前に、さまざまな数のロード命令を試してください。ポイントは、ターゲット レジスタを使用する前に、読み取りが発生するまでの時間を確保する必要があるということです。

注: Q4 ~ Q7 の使用は、不揮発性レジスタであるため危険です。Android では、これら (特に Q4) にランダムなガベージが表示されます。

于 2013-02-18T21:21:07.667 に答える