最適化技法

まだ実際のプロセッサが世の中に出ていない状態ではあるが、すでにCortex-M7に向けたプログラミングマニュアルがリリースされている。最適化にというよりもコード移植に関しては、たとえばこちらのApplication Noteが参考になる。とはいっても、先に述べた通り基本的にはCortex-M4までとCortex-M7はバイナリ互換だから、既存のプログラムが動かないというケースはほとんど無い。もちろんMCUだから、実際にはI/O空間やら周辺回路やらの違いに起因する問題はあるが、それは別の議論なのでここでは措いておく。先のApplication Noteによれば、Cortex-M4までとCortex-M7の違いはまずFPUにあるとしている。Cortex-M4はFPv4だがCortex-M7はFPv5に準拠しており、新たな命令が追加されて性能が改善しているとする。また、整数演算命令に関しては

  • タイミングをDelay loopで調整している場合、コードの変更が必要。
  • Cortex-M7では、起動時にIVT(Initial Vector Table)が0x00000000である必要がないので、IVTはVector Table Offset Registerから取得するように変更すべき。
  • Cortex-M7ではメモリが複数のバスに分散して配置される必要があり、またメモリのLoad/Storeが他の命令と並行に実行される可能性があるので、メモリアクセスの整合性を取るBarrier命令(DMB/DSB/ISB)を積極的に利用して整合性を取る必要が出る場合がある。
  • Cortex-M4までに用意されていたBit bandingの機能はCortex-M7には搭載されていないので、これを利用している場合はコードの変更が必要。
  • Flash Patchの機能もCortex-M7には無いので、(非常に稀ではあるが)利用している場合は変更が必要。
  • Cortex-M3/M4ではAuxilary Control Register経由でWrite BufferやMulti-cycle instruction interruptionをDisableに出来たが、Cortex-M7ではその機能が無くなった。
  • Cortex-M3/M4ではCCR(Configuration and Control Register)にDouble word stack alignmentのDisable/Enableの機能があったが、Cortex-M7では64bitバスになった関係で常にDouble word alignmentになり、Disableにすることはできなくなった。

といった細かな違いはあるが、概ね既存のコードはそのまま動くとする。

では性能改善は? というと、例えばLoad/Store UnitがALUと並行して動くようになったから、Cortex-M4ではPhoto15の様にLoad/StoreとALUをInterleaveで実施するように記述することで性能が改善するとしている。

Photo15:ただこれを手で記述するとなると、結構影響範囲が大きそうな気がする。あるいは将来のgccではこのあたりの最適化が進む可能性はあるが、そのあたりの予定は現時点では不明。当面は該当コードを手作業で直すしかなさそうだ

またMAC Unitに関しても、浮動小数点演算のサポートや1サイクルでのMAC演算が追加され(Photo16)、随分DSPに近くなった。特にMAC演算に関しては、Cortex-M4が加算・乗算それぞれ2cycleずつで、しかも同時には発行できなかったのに対し、Cortex-M7では1cycleで乗加算をまとめて実行できるようになっており、大幅に性能が改善しているとする(Photo17)。ただ、命令のスループットが4倍になったからといって、I/OのThroughputはそこまでは上がらない訳だが、それでも主要なMAC Unitを使う演算で2倍の性能を出せる(Photo18)のは、常時Load/Store Unitが稼動することで見かけ上従来の2倍の帯域が利用できるからということと考えて良いと思う。

Photo16:ついにペナルティ0のループが実装され、かなりDSPっぽくなってきた。とはいえ、FFTとかRing Bufferをこれで実装することまでは考えてないので、Circular addressing/bit-reverse addressingまではサポートしていない

Photo17:MAC UnitもLoad/Store Unitと並行して稼動できるので、Photo15の様にInterleaveで実施することで性能がさらに上げられる。ちなみにMAC演算のポイントは、acc1とかd1の演算で、Cortex-M4だとacc1 = b0 * Xn1;acc += d1;と2命令に分割しているのが、Cortex-M7だとacc1 = b0 * Xn1 + d1;と1命令で実施できる

Photo18:これまではALUとLoad/Storeが交互に動いていたが、Cortex-M7ではLoad/Storeをずっと動かしっぱなしにしながら並行してALUなりMACなりを利用できるからで、このあたりは整数演算性能の向上にも役立っていると思われる