NUCLEO-F401REをmbedのオンラインコンパイラで使う際FPUは有効になっている。

Nucleo F401REに搭載されたSTM32F401REは単精度FPUを搭載していながら1500円で買える貧乏人の味方である。

後輩からこれをmbedのwebコンパイラから使用する際にFPUが無効設定になっているとの情報を得た。

また、別の後輩からオフラインコンパイラ(Keil uVision)であればFPUを有効にできる旨(http://developer.mbed.org/media/uploads/hirokazu_yago/mbed-nucleo-f401re-offline-works.pdf)情報を得た。

二月ほど前にジャイロを使った角度推定で処理速度が出なくて困っていた私はなるほどこれが原因かと考え、確証を得るために急遽南米へ飛んだ。

検証

1.00001を1万乗するプログラムの実行にかかる時間を測定した。

#include "mbed.h"

Serial pc(USBTX, USBRX);
Timer timer0;
float num = 1.0f;

int main() {
    pc.baud(115200);
    pc.printf("start\n");
    timer0.start();
    for(int i=0;i<10000;i++){
        num *= 1.00001f;
    }
    pc.printf("num = %f time = %d\n", num, timer0.read_us());
}

結果

webコンパイラ 298us

uVision 298us

結論

webコンパイラでもFPUは有効である。まんまと踊らされた。

なお、上記資料にあるFPU有効化設定は現在既にwebコンパイラからエクスポートした時点で行われているのでしなくてよい。

以下のおまけ情報は処理を高速化するのにとても重要であるので読んだほうが良い。

おまけ① float指定

F401REのFPUは単精度である。ということは高速に処理できるのはfloatだけです。doubleはCPUで処理されます。

上記プログラムで小数には全部1.0fみたいにfloat型を明示してあるけどこれをサボるとdouble型として認識されるのでFPUは使用されずあなや。

具体的にはfloat型では298usで終わる上記処理がfを明示し忘れると32708usかかる。処理時間109倍である。あなや。

角度推定の処理速度が遅い理由はこれであると思われる。

おまけ② コンパイルオプション

uVisionでプロジェクトを開いた際の初期設定では、コンパイルオプションが色々無効になっているので、設定しないとwebコンパイラより遅いという残念な状態になる。

以下のようにコンパイルオプションを設定する必要があった。

設定するのは-O3とOptimize for timeとPlain char is signedだけでよい。

オフラインコンパイラ Keil uVision4 を使ってみる(その1) | mbed

/media/uploads/MACRUM/option_mod.png

実行時間は以下のとおりだった。

O0 1669us

O1 1073us

O2 1073us

O3 597us

O3,Optimize for time,Char 298us

FPU無効 32708us