富士通

FRファミリー一覧ページへ

開発にあたってのノウハウ

3. 命令処理スピードを上げるには

3.1 20bitアドレスモード設定を利用する

3.2 関数のスタック使用量が512byteを越えないように、ローカル変数の数を調整する

3.3 符号付1byte/2byte型データの多用は避ける

3.4 ループアンローリング最適化を使用する

3.5 インライン展開を利用する

3.6 標準ライブラリインライン展開を利用する

3.7 外部アクセス時には、内部動作周波数だけでなく、外部アクセス周波数十分な検討が必要

3.8 内部RAMの違いを理解する事が実行スピードを上げる秘訣

3.9 その他


3.1 20bitアドレスモード設定を利用する

外部変数を多用する場合32ビットアドレスをロードする命令が多数出現するためロードする場所によっては実行速度が遅くなるケースがあります。この対策として、コードあるいはデータが20bitアドレス空間(0x0~0xFFFFF)に配置されているRAM/ROMに配置可能である場合、20ビットアドレスモード(-K shortaddressオプション)の設定を推奨いたします。


3.2 関数のスタック使用量が512byteを越えないように、ローカル変数の数を調整する)

LD/ST命令ではFP相対アドレスが使用できます。しかしながら、16ビット命令長の制約から、指定可能なオフセットは最大-512~+508(4Byte型の場合)の範囲となっています。従って、512byteを越えるローカル変数領域を使用すると、スタックアドレス計算のための演算が増加しコードサイズ増加/アクセス効率が悪くなります。

そのため、関数のスタック使用量が512byteを越えないように、ローカル変数の数を調整して頂く事により、コードサイズの削減/アクセス効率の向上が図れます。

各関数のスタック使用量はSOFTUNE C/C++ Analyzerで確認することができます。

(注)ローカル変数の型が2byte型または1byte型の場合は、指定可能なオフセットはそれぞれ-256~254または-128~127となりますので、変数の型によって、効率良いコードの生成が可能なサイズは異なります。

<Cソース> <オフセットが-520の場合>
(上記以上のサイズを扱う時)
<オフセットが-4の場合>
(上記以内のサイズを扱う時)
a=10; LDI #10, R0 LDI #10, R0
LDI #-520, R13 ST R0, @ (FP, -4)
ST R0, @ (R13, FP)
8 byte 4 byte

3.3 符号付1byte/2byte型データの多用は避ける

FRアーキテクチャは符号付データのロード命令を持っていません。このため、符号付1byte/2byteデータをロードするときは、ロード後に符号拡張を行う必要があります。このため、符号付1byte/2byte型データを多用すると、符号なし型にくらべてコード量が増加します。

そのため、出来るだけ、符号なし型をご使用頂く事により、コードサイズの削減/アクセス効率の向上が図れます。

(注)Softune Compilerではchar型はunsigned char型として扱いますので、そのままお使いいただけます。

<Cソース> <signed char型の場合> <char型の場合>
a=b+c; LDI:20 #_b, R12 LDI:20 #_b, R12
LDUB @R12, R0 LDUB @R12, R0
EXTSB R0 LDI:20 #_c, R12
LDI:20 #_c, R12 LDUB @R12, R1
LDUB @R12, R1 ADD R1, R0
EXTSB R1 LDI:20 #_a, R12
ADD R1, R0 STB R0, @R12
LDI:20 #_a, R12
STB R0, @R12
24 byte 20 byte

3.4 ループアンローリング最適化を抑止する

ループアンローリング最適化は、ループ回数を減らすことにより実行速度の向上をはかるものです。
必要な個所にはループアンローリングを検討ください。以下にアンローリング前と後の例を示します。

<アンローリング前>
   for(i=0;i<6;i++){ a[i]=0;}

<アンローリング後>
   for(i=0;i<6;i+3){
         a[i]=0;
         a[i+1]=0;
         a[i+2]=0;
   }

しかしながら、この方法を使用すると、オブジェクトサイズが増加する傾向があります。


3.5 インライン展開を利用する

インライン展開最適化は、Cソース上で定義された関数に対して、関数呼出しの代わりに呼び出し先関数の処理を展開します。可能な限り実施することで実行速度が向上することが見込まれます。しかしながら、この方法を使用すると、オブジェクトサイズが増加する傾向がありますので、オブジェクトサイズを重視する場合は、この最適化を実施しない方が良い時があります。
(オブジェクトサイズが気になる場合は、-xautoオプション、-xオプション、#pragma inline、inline型修飾子(C++のみ)を使用しないで下さい。)

また、キャッシュ内蔵品種は、キャッシュミスが増加する場合もあることを考慮してインライン展開を指定する必要があります。


3.6 標準ライブラリインライン展開を利用する

標準ライブラリインライン展開は、標準関数の動作を認識して、標準関数のインライン展開および同じ動作をする、より高速な標準関数への置き換えを行います。
(オブジェクトサイズが気になる場合は、標準ライブラリインライン展開抑止(-Knolib)を指定する事により、標準ライブラリインライン展開が抑止されます。)


3.7 外部アクセス時には、内部動作周波数だけでなく、外部アクセス周波数十分な検討が必要

一般的に内部周波数が高ければ命令処理性能が高いと考えがちです。

しかしながら、外部バスアクセス時においては、内部動作周波数が速いからといって、命令処理性能が必ず向上するわけではありません。これは、外ROM品等で命令が格納されているFlash等のバス接続先のデバイスのアクセスタイムに大きく依存します。

以下に、MB91151Aのベンチマーク結果を例として示します。

下記の各動作周波数別の性能解析から分かりますように、内部32MHz/外部16.5MHz と内部25MHz/外部25MHzでは、後者の方が性能が良いことが確認できます。(なお、キャッシュ使用時には、キャッシュヒット率が良い場合、当然内部周波数の高い方が処理が早くなるために性能が向上しますので、上記の限りではありません。)

例:MB91151を使用した命令処理スピードと内部/外部動作周波数との関係

テストプログラム概要

test1 構造体/分岐/代入
test2 1次元配列初期化/分岐/代入
test3 1次元配列初期化/分岐/代入
Cashe OFF 70ns
FLASH
動作可能
60ns
FLASH
動作可能
STACK DATA CODE 速度比較(単位:usec)
test1 test2 test3 total
MB91151/サイズ優先(CPU33MHz 外FLASH16.5MHz 1wait) F-RAM F-RAM 外FLASH 580.2 19.5 666.4 1266.1
MB91151/速度優先(CPU33MHz 外FLASH16.5MHz 1wait) F-RAM F-RAM 外FLASH 557.3 18.9 659.3 1235.5
MB91151/サイズ優先(CPU33MHz 外FLASH16.5MHz 0wait) F-RAM F-RAM 外FLASH 386.9 13.0 445.3 845.2
MB91151/速度優先(CPU33MHz 外FLASH16.5MHz 0wait) F-RAM F-RAM 外FLASH 371.6 12.6 446.8 831.0
MB91151/サイズ優先(CPU25MHz 外FLASH25MHz 1wait) F-RAM F-RAM 外FLASH 386.9 13.0 443.1 843.0
MB91151/速度優先(CPU25MHz 外FLASH25MHz 1wait) F-RAM F-RAM 外FLASH 371.6 12.6 444.6 828.8
Cashe OFF 70ns
FLASH
動作可能
60ns
FLASH
動作可能
STACK DATA CODE MIPS
(Dhrystone1.1)
MB91151/サイズ優先(CPU33MHz 外FLASH16.5MHz 1wait) F-RAM F-RAM 外FLASH 3.63
MB91151/速度優先(CPU33MHz 外FLASH16.5MHz 1wait) F-RAM F-RAM 外FLASH 3.05
MB91151/サイズ優先(CPU33MHz 外FLASH16.5MHz 0wait) F-RAM F-RAM 外FLASH 5.25
MB91151/速度優先(CPU33MHz 外FLASH16.5MHz 0wait) F-RAM F-RAM 外FLASH 4.57
MB91151/サイズ優先(CPU25MHz 外FLASH25MHz 1wait) F-RAM F-RAM 外FLASH 7.00
MB91151/速度優先(CPU25MHz 外FLASH25MHz 1wait) F-RAM F-RAM 内FLASH 6.09
Cashe ON 70ns
FLASH
動作可能
60ns
FLASH
動作可能
STACK DATA CODE 速度比較(単位:usec)
test1 test2 test3 total
MB91151/サイズ優先(CPU33MHz 外FLASH16.5MHz 1wait) F-RAM F-RAM 外FLASH 474.4 2.5 107.9 584.8
MB91151/速度優先(CPU33MHz 外FLASH16.5MHz 1wait) F-RAM F-RAM 外FLASH 488.7 2.3 107.4 598.4
MB91151/サイズ優先(CPU33MHz 外FLASH16.5MHz 0wait) F-RAM F-RAM 外FLASH 318.6 2.3 102.9 423.8
MB91151/速度優先(CPU33MHz 外FLASH16.5MHz 0wait) F-RAM F-RAM 外FLASH 326.9 2.2 102.3 431.4
MB91151/サイズ優先(CPU25MHz 外FLASH25MHz 1wait) F-RAM F-RAM 外FLASH 321.2 3.0 125.8 450.0
MB91151/速度優先(CPU25MHz 外FLASH25MHz 1wait) F-RAM F-RAM 外FLASH 328.5 2.8 124.4 455.6
Cashe ON 70ns
FLASH
動作可能
60ns
FLASH
動作可能
STACK DATA CODE MIPS
(Dhrystone1.1)
MB91151/サイズ優先(CPU33MHz 外FLASH16.5MHz 1wait) F-RAM F-RAM 外FLASH 30.35
MB91151/速度優先(CPU33MHz 外FLASH16.5MHz 1wait) F-RAM F-RAM 外FLASH 25.95
MB91151/サイズ優先(CPU33MHz 外FLASH16.5MHz 0wait) F-RAM F-RAM 外FLASH 30.35
MB91151/速度優先(CPU33MHz 外FLASH16.5MHz 0wait) F-RAM F-RAM 外FLASH 25.95
MB91151/サイズ優先(CPU25MHz 外FLASH25MHz 1wait) F-RAM F-RAM 外FLASH 30.35
MB91151/速度優先(CPU25MHz 外FLASH25MHz 1wait) F-RAM F-RAM 内FLASH 25.95

3.8 内部RAMの違いを理解する事が実行スピードを上げる秘訣

実行速度を早くするためにはできるだけチップ内部に各領域を配置することが有効です。
FRシリーズでは、複数のバスにそれぞれのRAMが接続されており、それぞれの違いを理解するためにはバスの違いを理解する必要があります。以下にFRシリーズのバス構造を紹介します。
FRコアは命令バスとデータバスが独立しています。(ハーバードアーキテクチャ)I-busは、命令用バス、D-busはデータ用バスです。F-busは命令、データが共存できるプリンストンバスです。バスコンバータを介してI-bus、D-busに接続されます。それぞれのバスについているRAMをここではI-RAM、D-RAM、F-RAMと呼びます。

  • I-RAMは命令(CODE領域)を配置することで1cycle命令の実行が可能です。
  • D-RAMはデータ(DATA/STACK領域等)を配置することで1cycleアクセスが可能です。
    当然、D-RAMにはCODE領域は配置できません。
  • F-RAMはCODE/DATA/STACK領域等どちらも配置可能ですが、
  • バスコンバータを介しているためにI-RAM/D-RAMよりはサイクルがかかります。

リンカで配置する際には上記のRAM領域を考慮する事により、実行速度の向上が図れます。


3.9 その他

メモリコピーに着目
構造体代入、構造体引数、構造体戻り値、strXXX/memXXXのように領域をコピーするコードが実行速度のネックになっている場合があります。このようなコードに着目して可能であればコンパイラ出力コードに問題がないか検討してください。特に、strXXX/memXXXライブラリは汎用的に作成されているので、取り扱うデータの配置境界や、データ長があらかじめ分かっている場合、ライブラリ呼び出しにせずに専用処理を記述した方が高速になります。当然ですが、バイト単位よりワード単位でのコピーの方がより高速になります。

実行時のライブラリ呼び出しを回避
実行時のライブラリ呼び出しに着目して、実命令で演算できないデータ型(long型等)をできるだけ回避してください。

参照回数の多い構造体メンバーを先頭へ配置する
構造体メンバーのアクセスでは 先頭アドレス+オフセットを計算して実際の配置アドレスを求めます。
先頭メンバーは オフセット= 0 であるために計算が不要となります。静的なアクセス頻度が高いメンバーがある場合、先頭に配置可能か検討してください。

構造体を返す関数のvoid化
構造体を返す関数では作業領域への構造体転送が発生します。代入先の構造体のアドレスを引数で渡し、直接代入することでvoid関数化することができます。

引数は4個以内にする
4個以内の引数はレジスタ渡しとなるためにスタックアクセスのためのコードが不要になり実行速度が改善されます。無駄に渡している引数がある場合は、削減するよう検討してください。