Team for GR-PEACH Producer Meeting

Lチカ議論

30 Nov 2014

昨日、Lチカで負論理駆動の件に関して、質問させていただきました。
http://developer.mbed.org/questions/5446/1417268131/
今日、手元にあったいくつかのmbedでLチカの処理スピードを計測してみました。
使用したプログラムは、下記のものです。

Import programGR-PEACH_performance_check_0

Performance check program for LED blinky


結果は下記のようになりました。
/media/uploads/kenjiArai/performance.png
CPU性能と一対一で対応していないように見えるのは、やはりハードウェアレイヤーの隠ぺいの仕方に各ベンダーの個性が出ているからでしょうか?
昨日もQ&Aの中で、ADC処理スピードに関する質問がありましたが、GR-PEACHの実力に見合った結果が出るように期待します。
別にLチカが早い遅いと一喜一憂するつもりはありませんが、ほかのファンクション開発にも影響を与える基本的な部分ではないかと思い議論の口火を切りたいと思います。

01 Dec 2014

DigitalOutクラスを介さずに直接アクセスしてみたらどうだろうと思いやってみましたが、あんまり速くないですね。

GPIO

#include "mbed.h"

int main()
{
    //init GPIO - DIO0:P2_15
    GPIOPIBC2 = GPIOPIBC2 & 0x7fff;
    GPIOPBDC2 = GPIOPBDC2 & 0x7fff;
    GPIOPM2   = GPIOPM2   | 0x8000;
    GPIOPMC2  = GPIOPMC2  & 0x7fff;
    GPIOPIPC2 = GPIOPIPC2 & 0x7fff;

    GPIOPIBC2 = GPIOPIBC2 & 0x7fff;
    GPIOPM2   = GPIOPM2   & 0x7fff;

    while(true) {
        GPIOP2 = GPIOP2 | 0x8000;
        GPIOP2 = GPIOP2 & 0x7fff;
    }
}

/media/uploads/YuuichiAkagawa/gr-peach_gpio.jpg

1回480nsなので、約1MHzといったところでしょうか。 Cortex-Aのアーキテクチャの詳細は把握してないのですが、ハードウェアマニュアル(Rev.1.00)のP.5-3の表によるとGPIOは周辺バス2に接続され、バス周波数はP0(33.33MHz)ということになっています。
Cortex-AはGPIOを全力でぶん回すような使い方をするものではないと思うので、こんなもんなんでしょうか。

それから、GR-PEACHのプログラムメモリは外付けSPIフラッシュから直接実行する仕様だと思います(ブートモード3)。
キャッシュに載るくらいの大きさならば問題無いのだろうと思いますが、ROMに置いたデータの読み込みは遅いのかなと。
試しに、1MBほどのデータをROMに置き、それを読み込むプログラムを作ってみましたが、32bitずつ読み出して24MB/s程度でした。
RAMからだと238MB/s程度だったので、10倍ほど差があるようです(CPUが遊んでしまいますね)。

400MHzのCortex-Mではないと認識して向き合う必要があるのだと感じています。

01 Dec 2014

Nucleo F411REは、mbedの初期化をそのまま使うとシステムクロック100MHzとなり、GPIOはその時50MHzで駆動されています。
F411が早かった要因はクロックスピードにありそうですね。
Akagawaさんの調査とコメントを拝見すると、スピードの優劣は私が指摘したハードウェアレイヤーの隠蔽の仕方(ソフトの作り方)の問題ではなく、このCPUの設計思想から来てるんですね!
何にもCPUの予備知識がなくて、ソフトの作り方だと指摘したことを反省します。仕様では仕方ありません。
私も書き込みの遅い要因とその対応は、別のテーマとして議論したいと思っています。その節はご教示願います。

02 Dec 2014

いえいえ、あくまでも私見なので中の人の公式見解を聞きたいです。

02 Dec 2014

おーい、中の人〜(笑)

04 Dec 2014

本件、回答が滞り申し訳ございません。 現在、解析中で、詳細が判明次第、情報展開させていただきたいと思います。

07 Dec 2014

現在提供している環境は、 ご指摘のように、外付けシリアルフラッシュ上から直接実行を行っています。
提示いただいたプログラムに対してキャッシュの有無で速度を計測しました。

  • キャッシュ有効
    L1、L2  ON
    分岐予測 ON
Start measurement on TARGET_RZ_A1H
Running speed 0.7510[uS]
  • キャッシュ無効
    L1、L2  OFF
    分岐予測 OFF
Start measurement on TARGET_RZ_A1H
Running speed 2.2390[uS]

上記から、キャッシュは効いていると考えられます。

08 Dec 2014

「GPIOのパタパタ性能はこんなもん」という理解で良いのですね。了解しました。

09 Dec 2014

「GPIOのパタパタ」の話に限定すると、GPIOの制御をPSRレジスタを用いることでレジスタのアクセス数を低減させることができます。
PSRは上位16bitで操作する端子を選択し、下位16bitで該当する端子のレベルを決定します。

PSRレジスタ使用例

//P0_0をhighにする
PSR0=0x00010001;
//P0_3をlowにする
PSR0=0x00080000;
//上記を同時に行う
PSR0=0x00090001;

上記を応用すると、下記変更で全体のGPIOアクセスの高速化(とは言ってもレジスタアクセス1回分ですが)を図ることができます。
本変更は検証中のもので、動作確認およびライブラリへの反映は現在生じている諸問題が解決した後になります。

gpio_api.c (36)

    obj->reg_set = (volatile uint32_t *) PSR(group);


gpio_object.h (33)

static inline void gpio_write(gpio_t *obj, int value) {
    *obj->reg_set = (obj->mask << 16) | ((value!=0) ? obj->mask : 0);
}


全体の高速化という話になると、プログラムを内蔵RAMで動作させることで性能が上がりますが、そのためにはオフライン環境(GCC環境)である必要があります。GCC対応については、一通り、ARMCCでの機能拡充が落ち着いたところでの対応を予定していますので、申し訳ありませんが、それまでお待ちください(1月になる見込みです)。

10 Dec 2014

ありがとうございます。そういうレジスタがあるんですね。マニュアルでも確認できました。
実際に240nsでパタパタするのを確認できました。※でもまあ、こんなもんですよね...。

全然急いでいる話しでは無いので後回しで構いません。他の件を優先してください。

(2014.12.10追記)
あくまでもご参考までという話しになりますが、「ただパタパタするだけの部分」だとArduinoの方が速いのです。
こんなコードを実行すると、125nsでパタパタします。16MHzの8bitマイコンの方が倍速い。

arduino_gpio.ino

void loop()
{
  PORTD |= _BV(2);
  PORTD &= ~_BV(2);
  PORTD |= _BV(2);
  PORTD &= ~_BV(2);
}

もちろん、PEACHのCPUコアは400MHzで動作しているので、ループに要する時間は上記の100MHzサンプリングのロジアナ計測では捕捉できないくらい速いです。1クロック2.5nsといったところでしょうか。(Arduinoだと750nsほどかかる)。
このクラスのマイコンだとI/Oのコストは非常に高い。約100倍。
delay_ms()のバラツキでの議論でも気になりましたが、ticker読むのにもレジスタアクセスするので、これのコストもバカにならないんだなと思いました。
だからなんだという話しではありませんが、所感でした。