6

私の組み込みシステムのクラスでは、指定された C 関数 AbsVal を ARM アセンブリに再コーディングするよう求められました。私たちができる最善のことは3行だと言われました。私は 2 行の解決策を見つけようと決心し、最終的にはそうしましたが、今私が抱えている問題は、実際にパフォーマンスを低下させたのか、それとも増加させたのかということです。

C コード:

unsigned long absval(signed long x){
    unsigned long int signext;
    signext = (x >= 0) ? 0 : -1; //This can be done with an ASR instruction
    return (x + signet) ^ signext;
}

TA/教授の 3 行ソリューション

ASR R1, R0, #31         ; R1 <- (x >= 0) ? 0 : -1
ADD R0, R0, R1          ; R0 <- R0 + R1
EOR R0, R0, R1          ; R0 <- R0 ^ R1

私の2行ソリューション

ADD R1, R0, R0, ASR #31 ; R1 <- x  + (x >= 0) ? 0 : -1
EOR R0, R1, R0, ASR #31 ; R0 <- R1 ^ (x >= 0) ? 0 : -1

潜在的なパフォーマンスの違いを確認できる場所がいくつかあります。

  1. Arithmetic Shift Right 呼び出しを 1 つ追加
  2. 1 つのメモリ フェッチの削除

では、どちらが実際に速いのでしょうか。プロセッサまたはメモリのアクセス速度に依存しますか?

4

2 に答える 2

6

これは、別の 2 つの命令バージョンです。

    cmp     r0, #0
    rsblt   r0, r0, #0

これは単純なコードに変換されます:

  if (r0 < 0)
  {
    r0 = 0-r0;
  }

そのコードは、Cortex-A8 や A9 などの最新の ARM-CPU コアでもかなり高速になるはずです。

于 2013-05-13T16:55:49.227 に答える
4

ARM.com にアクセスして、Cortex-M3 のデータシートを入手してください。3-4 ページのセクション 3.3.1 に命令のタイミングがあります。幸いなことに、Cortex-M3 では非常に簡単です。

これらのタイミングから、完全な「待機なし」システムでは、教授の例が 3 サイクルかかることがわかります。

ASR R1, R0, #31         ; 1 cycle
ADD R0, R0, R1          ; 1 cycle
EOR R0, R0, R1          ; 1 cycle
                        ; total: 3 cycles

あなたのバージョンは2サイクルかかります:

ADD R1, R0, R0, ASR #31 ; 1 cycle
EOR R0, R1, R0, ASR #31 ; 1 cycle
                        ; total: 2 cycles

したがって、理論的には、あなたの方が高速です。

「メモリーフェッチの廃止」とおっしゃっていますが、本当ですか?それぞれのルーチンの大きさはどのくらいですか? Thumb-2 を扱っているため、16 ビットと 32 ビットの命令が混在しています。それらがどのように組み立てられるか見てみましょう:

それらのバージョン (UAL 構文に合わせて調整):

    .syntax unified
    .text
    .thumb
abs:
    asrs r1, r0, #31
    adds r0, r0, r1
    eors r0, r0, r1

組み立てる:

00000000        17c1    asrs    r1, r0, #31
00000002        1840    adds    r0, r0, r1
00000004        4048    eors    r0, r1

それは 3x2 = 6 バイトです。

あなたのバージョン (ここでも、UAL 構文に合わせて調整されています):

    .syntax unified
    .text
    .thumb
abs:
    add.w r1, r0, r0, asr #31
    eor.w r0, r1, r0, asr #31

組み立てる:

00000000    eb0071e0    add.w   r1, r0, r0, asr #31
00000004    ea8170e0    eor.w   r0, r1, r0, asr #31

それは 2x4 = 8 バイトです。

そのため、メモリ フェッチを削除する代わりに、実際にはコードのサイズを増やしています。

しかし、これはパフォーマンスに影響しますか? 私のアドバイスは、ベンチマークすることです。

于 2013-05-13T23:11:30.977 に答える