0

プログラムでCPU周波数を特定するために使用しようとしている小さなプログラムがあります。

私のプログラムは次のように構成されています。

  • アラームを設定する
  • while(1)ループでレジスタをインクリメントする
  • 計算速度SIGALRM

当初、私は使用していました

register unsigned int cycles asm("r6");  
...  
while(1)
    cycles++;

objdump を使用すると、これが実際に次のように変換されることに気付きました。

9aa0:       e1a03006        mov     r3, r6  
9aa4:       e2833001        add     r3, r3, #1  
9aa8:       e1a06003        mov     r6, r3  
9aac:       eafffffb        b       9aa0 <estimate_from_cycles+0x1cc>  

なぜこれが 3 つの命令に変換されるのかわからなかったので、代わりにインライン アセンブリを使用してみました。

register unsigned int cycles asm("r6");  
...  
while(1)
    asm("add r6, r6, #1);

これは次のように翻訳されました。

9aa0:       e2866001        add     r6, r6, #1  
9aa4:       eafffffd        b       9aa0 <estimate_from_cycles+0x1cc>  
  • 以前の実装が 3 つの命令に変換されたのはなぜですか?
  • ARM プラットフォームでは、b <label>命令に 3 サイクルかかります。ただし、ARM での減算演算は、1 サイクルのみを使用します。
    • PCレジスタから減算する方法はありますか?
    • 減算はPCでも許可されていますか?
    • 同じロジックを実装するために必要なサイクル数を減らす他の方法はありますか?

編集: CodeSourcery の arm-none-linux-gnueabi-toolchain を最適化なしで使用しています

4

1 に答える 1

1

最適化を有効にしていないため、実装が 3 つの命令に変換された可能性が非常に高いです。

ただし、簡単なテストから、インライン アセンブリを記述する必要があるように見えます。-O3 -fomit-frame-pointer

void test(void) {
        register unsigned int cycles asm("r6");
        while(1) cycles++;
}

ルーチンは単純に最適化されました

00000000 <test>:
   0:   eafffffe    b   0 <test>

volatileコンパイラーは、CPU レジスターへの書き込みには (メモリとは異なり) 副作用がないことを確実に認識しているため、追加しても無駄です。

その他の質問にお答えしますと、

  • PCレジスタから減算する方法はありますか?
  • 減算はPCでも許可されていますか?

はい、確かに。しかし、それでも1サイクルかかるかどうかはわかりません。

  • 同じロジックを実装するために必要なサイクル数を減らす他の方法はありますか?

余談ですが、測定の開始時と終了時にプロセスが切り替わる可能性があるため、ロジックではあまり正確な結果が得られません。

あなたが期待している:

<                    your process                     >
|<---------------your alarm duration----------------->|

いつ、それはおそらくもっと似ています(|コンテキストスイッチはどこにありますか):

<your process> | <other processes ...> | <your process>
|<---------------your alarm duration----------------->|
于 2013-11-01T03:38:51.040 に答える