コンテンツ
- コード実行時間を実験的に測定する方法
- 1.マイクロコントローラーの処理能力とメモリサイズを知る
- 2.コードサイズを最適化するための変数の選択
- 3.コード実行時間の最適化のための変数の選択
- 4.算術演算の最適化
- 5.集中的な計算にはDSP対応のマイクロコントローラーを使用します
- DSPプロセッサがALUよりも高速に実行できる命令は次のとおりです。
- マイクロコントローラのDSPエンジンを使用するには、次のことが必要です。
- 6.割り込みの操作
- 7.利用可能な最良のコンパイラを使用する
- 8.条件文をインテリジェントに使用する
- 9.インライン関数を使用する
- 10.デクリメントループを使用する
- まとめ
著者は、dsPicマイクロコントローラーを使用して最終年度のエンジニアリングプロジェクトを完了し、これらのデバイスに関する広範な洞察を得ました。
マイクロコントローラのC言語コードは、特定の高度なアプリケーションで最適化が必要な場合があります。このコードの最適化は、次の2つの重要なことを減らすために実行されます。
- コードサイズ: マイクロコントローラーは、RAMのサイズが限られているため、限られたデータと命令を格納できます。したがって、使用可能な命令とデータメモリを最も効率的に利用できるように、コードを最適化する必要があります。
- コード実行時間: マイクロコントローラは、一度に1つの命令を実行するシーケンシャルデバイスです。各アセンブリ命令は、それ自体を実行するために特定のクロックサイクル数を消費します。したがって、コードを最適化して、必要なタスクを最小限のクロックサイクルまたはアセンブリ命令で実行できるようにする必要があります。コードが使用するクロックサイクルが少ないほど、実行速度は速くなります。これは、処理時間が最小限に抑えられるため、アプリケーションをより高速に実行できることを意味します。
この記事では、マイクロコントローラーコードのサイズと実行時間を短縮するために使用できるヒントとコツを紹介します。
Microchip社のMplabX開発IDEを使用して、必要に応じて例を示します。
コード実行時間を実験的に測定する方法
コードが実際にリアルタイムで実行されるのにかかる時間を知るには、実験的に測定する必要があります。ロジックアナライザーは、コードの実行時間を測定するために便利に使用でき、興味のある人は、私から電子メールでこのプロセスについて問い合わせることができます。これの横に:
- 一部のコンパイラには、コードが消費するクロックサイクルをカウントする機能があります。
- マイクロチップ社のICD3などの一部のデバッガーは、ストップウォッチを介して実行時間を直接測定できます。
1.マイクロコントローラーの処理能力とメモリサイズを知る
マイクロコントローラーの処理速度の真の姿を示すのは、常にクロック周波数(Mhz)であるとは限りません。より現実的な尺度は、MIPS(1秒あたりのメガ命令)またはMCUが1秒間に実行できる命令の数です。
MCUは通常、ハイエンドカテゴリの60〜70MIPSから20MIPS8ビットAVRの範囲です。高MIPSマイクロコントローラーはローエンドデバイスよりも高価になる可能性が高いため、ここではコストと処理速度のトレードオフがあります。
マイクロコントローラには、データとプログラムコードを格納するための個別のメモリがあります。それらの両方のサイズは、データシートから見つけることができます。コードがかなり大きい場合は、より大きなメモリサイズのMCUが必要になることがあります。
2.コードサイズを最適化するための変数の選択
マイクロコントローラのデータメモリは限られており、通常は1〜4Kバイトの範囲です。この場合、保存される日付の予想される範囲に応じて、最も適切な変数タイプを選択するのが賢明です。次の表は、これらの変数をまとめたものです。
変数タイプ | バイト単位のサイズ | 範囲 |
---|---|---|
ブール | 1 | 0または1のみ |
char | 1 | -128〜127 |
int | 2 | -32,768〜32,767 |
unsigned int | 2 | 0〜65,535 |
長いです | 4 | -2,147,483,648から2,147,483,647 |
浮く | 4 | 小数点以下6桁まで正確 |
ダブル | 8 | 小数点以下15桁まで正確 |
ロングダブル | 10 | 小数点以下19桁まで正確 |
例:
- 2つの変数XとYを加算し、結果をZに格納するが、加算後にZの値が65,535を超えると予想される場合、Zはlongとして宣言され、XとYはunsignedとして宣言されます。 int、XとYの値も負になるとは予想されていません。これにより、すべての変数がlongとして宣言された場合に使用されていたはずの、データメモリに04バイトが節約されます。
- 値が整数であると予想される2つの変数XとYは除算されますが、除算の結果は10進数になり、XとYはintと宣言され、結果はfloatまたはdoubleと宣言されます。必要な精度。
多数の要素を含む配列を宣言する場合、データ型の選択が重要になる場合があります。
3.コード実行時間の最適化のための変数の選択
- 浮動小数点計算は固定小数点計算よりも時間がかかることは確立された事実です。 10進値が不要な浮動小数点変数は使用しないでください。可能な限り、符号なし整数を処理します。
- ローカル変数はグローバル変数よりも優先されます。変数が関数でのみ使用される場合、グローバル変数へのアクセスはローカル変数よりも遅いため、その変数で宣言する必要があります。
- 8ビットMCUは、生成されるアドレスの長さにより、1バイトサイズの変数へのアクセスが速くなり、16ビットMCUは2バイト変数へのアクセスが容易になります。
4.算術演算の最適化
算術演算は、次の方法で最適化できます。
- サインやその他の三角関数、またはコードで結果を事前に知ることができるその他の演算を評価する代わりに、事前に計算された値のルックアップテーブルを使用します。
- サインルックアップテーブルがすでにメモリに格納されている場合、90度に相当する配列ポインタを進めることによってコサインを評価できます。
- 4つの算術演算の中で、除算と乗算が最も処理時間を要します。実際には、浮動小数点値の場合、数百マイクロ秒程度の範囲になる可能性があります。
- 除算と乗算の代わりにビットシフト命令を使用します。右シフト命令3は2で除算するのに役立ちます3 ここで、左シフト命令として1は2を掛けるのに役立ちます1.
5.集中的な計算にはDSP対応のマイクロコントローラーを使用します
一部のマイクロコントローラには、従来のALU以外のDSP処理ユニットがアーキテクチャに組み込まれています。このDSPエンジンは、最小のクロックサイクル数(ほとんどの場合1つ)でALUよりも何倍も高速に算術計算を実行するように設計されています。
DSPプロセッサがALUよりも高速に実行できる命令は次のとおりです。
- ビットシフトおよび回転命令。
- 乗算、除算、およびその他の算術演算。
- サインおよびその他の三角関数の評価。
- FFT、DFT、畳み込み、FIRフィルタリングなどのすべてのDSP操作。
マイクロコントローラのDSPエンジンを使用するには、次のことが必要です。
- 個別のDSPライブラリがプロジェクトに組み込まれています。
- 関数の名前は、C言語の標準的な数学ライブラリとは異なります。これらのライブラリと関数のドキュメントは、それぞれのメーカーのWebサイトから入手できます。
- DSPエンジンは、異なる変数タイプ「フラクショナル」を利用します。 dspライブラリ関数に進む前に、分数型変数の使用方法を学習してください。
標準の数学ライブラリ関数は、ALUアセンブリ命令に変換されるため、DSPエンジンを呼び出さないことに注意してください。
6.割り込みの操作
次のような特定の機能を実行するには、割り込みを使用します。
- ADC値の読み取り。
- UARTからの送受信。
- PWMデューティサイクルレジスタの更新。
- CANまたはI2C通信。
割り込みは、関数呼び出しまたはインラインコードを介して本体で実行する場合と比較して、これらの関数を迅速に処理します。
割り込みも必要な場合にのみトリガーされますが、本体でコーディングされている場合、コードはwhile(1)ループのすべての反復で実行されます。
7.利用可能な最良のコンパイラを使用する
コンパイラーは、適切に構成されていれば、コードをC言語からアセンブリ言語に変換しながら、上記で説明した最適化の一部を自動的に実装できます。コンパイラーで最適化オプションを探し、可能であれば、より強力なコードオプティマイザーであるコンパイラーのプロフェッショナルバージョンにアップグレードします。
8.条件文をインテリジェントに使用する
- 一連のif-elseステートメントを使用する場合は、最も可能性の高い条件を最初に保持します。このようにして、MCUは、真の状態を見つけた後、すべての状態をスキャンする必要がなくなります。
- switch-caseステートメントは、通常、if-elseの方が高速です。
- 一連のステートメントの代わりに、ネストされたif-elseステートメントを使用します。多くのステートメントを持つif-elseブロックは、最悪の場合(最後の)条件を最適化するために、より小さなサブブランチに分割される場合があります。
9.インライン関数を使用する
コード内で1回だけ使用される関数は、静的として宣言できます。これにより、コンパイラはその関数をインライン関数に最適化するため、関数呼び出し用にアセンブリコードが変換されません。
- 関数は、キーワード「static」を使用してインラインで宣言できます。
10.デクリメントループを使用する
デクリメントされたループは、インクリメントされたループと比較して、生成されるアセンブリコードが少なくなります。
これは、インクリメントループでは、ループインデックスをすべてのループの最大値と比較して、ループインデックスが最大値に達しているかどうかを確認するために、比較命令が必要になるためです。逆に、デクリメントループでは、ループインデックスのデクリメントされた結果がゼロに達すると、SREGにゼロフラグを設定するため、この比較は不要になります。
ループを100回繰り返す必要がある場合、ループから1つの命令を減らすと、100回実行されるのを回避できるため、ループを何度も繰り返す必要がある場合は、影響がより大きくなる可能性があります。
まとめ
これらのヒントは役立つかもしれませんが、それらの真のアプリケーションと効力は、プログラマーのスキルと彼がコードに対して持っているコマンドに依存します。プログラムのサイズが常に実行時間を決定するとは限らないことを忘れないでください。一部の命令は他の命令よりも多くのクロックサイクルを消費する可能性があるため、プログラムのスキルがその役割を果たす必要があります。
この記事は正確であり、著者の知る限り真実です。コンテンツは情報提供または娯楽目的のみであり、ビジネス、財務、法律、または技術的な問題に関する個人的な助言または専門的なアドバイスに代わるものではありません。