STM32 計算速度データ
2019年09月12日 カテゴリー:STM32 エフェクター
デジタルエフェクターでリアルタイムにデジタル信号処理をする場合、計算が間に合わずまともな音が出なくなるという可能性があります。そこで、様々な計算方法についてどの程度処理時間がかかるのか確認しておくことにしました。使ったのはNUCLEO-F401REで、FPU(浮動小数点演算処理装置)を備えています。開発環境はSTM32CubeIDE(1.0.2)です。
経過時間を確認するには、CPUのクロックサイクルのカウント数(以下サイクル数)を利用すると便利です。下記の記載をしておくと、サイクル数を確認できるようになります。(参考ページ→ARMのData Watchpoint and Trace Unitを使って処理時間計測をしてみよう)
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
そして下記のようにコードを書きます。「DWT->CYCCNT」に現在のサイクル数が入ります。コンパイル時に最適化されないように、volatileを入れ、サイクル数を変数として使うことにします。
volatile uint32_t start = 0;
volatile uint32_t stop = 0;
volatile uint32_t ivar[50] = {};
volatile uint32_t cnt[50] = {};
start = DWT->CYCCNT; // 開始時サイクル数
ivar[0] = start; // 計測したい処理
stop = DWT->CYCCNT; // 終了時サイクル数
cnt[0] = stop - start; // 処理にかかったサイクル数
上記「変数の代入」を基準として、処理を追加した場合にどのぐらいサイクル数が増えるかを確認しました。例えば乗算の場合、「ivar[1] = start * stop;」のようにして、変数の乗算を1つ追加するといった具合です。定数を使うと事前に計算されてしまう場合があるため、全て変数を使います。
コンパイル時の最適化オプション「O0(最適化なし)」と「Ofast(最速最適化)」での違いも確認します。1000回平均値ですが結果が結構変わるときがあり、あまり正確ではなさそうです。
<32ビット整数(uint32_t)>
サイクル数(O0) | サイクル数(Ofast) | |
何もしない | 8 | 4 |
代入(=)※基準 | 16 | 7 |
加算(+) 減算(-) 乗算(*) | 5 | 3 |
除算(/) | 9 | 7 |
剰余演算(%) | 11 | 8 |
各ビット演算(& | ! ^ >> <<) | 5 | 3 |
<32ビット浮動小数点数(float)>
サイクル数(O0) | サイクル数(Ofast) | |
代入(=)※基準 | 16 | 7 |
加算(+) 減算(-) 乗算(*) | 5 | 4 |
除算(/) | 17 | 17 |
C言語標準ライブラリmath.hにある数学の関数については以下の通りです。
サイクル数(O0) | サイクル数(Ofast) | |
sqrtf | 51 | 16 |
logf | 189 | 189 |
expf | 216 | 207 |
powf | 565 | 571 |
sinf | 82 | 79 |
sinhf | 286 | 283 |
atanf | 189 | 178 |
CMSIS-DSPライブラリを導入し、とりあえず2つの関数を使ってみました。(参考ページ→STM32 CubeIDE環境で、CMSIS-DSPを使う方法)
サイクル数(O0) | サイクル数(Ofast) | |
arm_sqrt_f32 | 91 | 13 |
arm_sin_f32 | 56 | 52 |