3

[質問の詳細をできる限り詳しく説明したいので、大量のテキストが届きます。]

Cortex-M0 用に手書きの ARM アセンブリ コードを最適化する作業を行っています。私が使用しているボードは、STM32F051R8 コントローラーを搭載した STMicro STM32F0Discovery です。コントローラは 48 MHz で動作しています。

残念ながら、最適化を行っているときにかなり奇妙なサイクル カウントが得られます。

たとえばnop、コードのループにシングルを追加すると、合計で 2 サイクルが追加されます (2 回ループ)。ただし、これを行うと、約 1800 サイクル余分に追加されます。ここで、エクストラnop(合計 2nop秒) を追加すると、サイクル カウントは予想される 4 サイクルだけ増加します。

以下のコード例でも同様の奇妙な結果が得られます。コード例は、上部の抜粋を示しています: c = 25 * a + 5 * b. 一番下の抜粋はc = 5 * (5 * a + b). したがって、必要な が 1 つ少ないため、一番下のほうが高速になるはずmovです。ただし、これを変更します。

movs r4, #25
muls r3, r4, r3
add  r2, r3 

ldrb r3, [r6, #RoundStep]
movs r4, #5
muls r3, r4, r3

add  r2, r3

これに:

movs r4, #5
muls r3, r4, r3 

ldrb r5, [r6, #RoundStep]
add r3, r5
muls r3, r4, r3

add  r2, r3

予想される1サイクルだけ速度が上がるのではなく、速度が1000サイクル程度低下します...

サイクルをカウントするには、SysTick カウンターを使用し、最大値からカウントダウンし、オーバーフロー割り込みでオーバーフロー カウンターを増やします。これに使用しているコードは、ARM Web サイトからの抜粋とほぼ同じですが、使用している Cortex-M0 用に書き直されています。私のコードは十分に高速であるため、測定中にオーバーフロー割り込みが発生することはありません。

ここで、カウンターが間違った値を示しているのではないかと考え始めたので、手元にあった TI Stellaris LaunchPad のコードも書きました。これは 80 MHz で動作する Cortex-M4F です。このコードは、特定のピンがハイに保持されているサイクル数を測定します。もちろん、M0 のクロックと M4F のクロックは同期して実行されていないため、報告されたサイクル カウントは少し異なります。これは、測定されたサイクル カウントの非常に低い加重指数平均を取ることで「修正」されます ( avg = 0.995 * avg + 0.005 * curCycles) と測定を 10000 回繰り返します。

M4F で測定された時間は M0 で測定された時間と同じであるため、「残念ながら」SysTick カウンターは M0 で正常に動作しているようです。

最初は、これらの余分な遅延がパイプラインのストールによって引き起こされたものだと思っていましたが、M0 は単純すぎて、M0 のパイプラインに関する詳細な情報が見つからないため、確認できませんでした。 .

だから、私の質問は:ここで何が起こっているのですか?makeを 1 つ追加するnopと関数に 1000 サイクル/ループが余分にかかるのに、2 つnopの s を追加してもサイクル数が 2 だけ増加するのはなぜですか? 命令を削除するとコードの実行速度が遅くなるのはなぜですか?

4

1 に答える 1