1

私は組み込みソフトウェアを (もちろん C を使用して) プログラミングしましたが、現在、システムの実行時間を改善する方法を検討しています。私のシステムで最も重要な単一モジュールは、ネストされた非常に大きな for ループ モジュールです。

そのモジュールは、最大 122500 回ループする 2 つのネストされた for ループで構成されています。まだそれほど多くはありませんが、問題は、ネストされた for ループ内に、別のソース ファイルにある関数への関数呼び出しがあることです。その特定の関数は、常に 22500 回ループするネストされた別の 2 つの for ループで主に構成されています。そのため、関数呼び出しを 122500 回行う必要があります。

私は、呼び出される関数をより軽量で短くしました (それでも、正常に機能します)。そして今、その関数呼び出しをはぎ取って、最初の 2 つの内部にそのプロセスを直接記述した方が速いのではないかと考え始めました。ループ?

そのシステムのプロセッサは ARM7TDMI で、その周波数は 55MHz です。システム自体はタイム クリティカルではないため、リアルタイム対応である必要はありません。しかし、その義務をより速く処理できるほど、より良いものになります。

また、fors の代わりに while ループを使用した方が高速でしょうか? また、実行時間を改善する方法についてアドバイスをいただければ幸いです。

-ザプレック

4

6 に答える 6

19

試してみてください!!

ほぼ間違いなく違います。通常、関数呼び出しのオーバーヘッドはそれほど大きな問題ではありませんが、10 万回を超えると増加し始めます。

...しかし、それが実際の違いを生むかどうかは、試してみて結果のタイミングを計った後、あなただけが答えられるものです.

forvsについてwhileは ... ループを変更するときに実際に動作を変更しない限り、問題にはならないはずです。疑わしい場合は、コンパイラに両方のアセンブラコードを吐き出させて比較してください...または単に変更して時間を計ってください。

于 2010-05-04T19:57:01.853 に答える
3

コンパイラがどの最適化を行っているかが常に明確であるとは限らないため、行う最適化には注意する必要があります。事前最適化は、よくある間違いです。コードが読みやすく、保守が容易であること、またはわずかに高速であることは重要ですか? 他の人が示唆しているように、最良のアプローチは、さまざまな方法をベンチマークし、顕著な違いがあるかどうかを確認することです.

コンパイラが最適化の方法で多くのことをしていると思わない場合は、C を最適化する際の古い概念を調べます (SO または Google で検索すると、いくつかの適切なリンクが提供されるはずです)。

于 2010-05-04T20:02:11.217 に答える
2

ARM プロセッサには命令パイプライン (キャッシュ) があります。プロセッサが分岐 (呼び出し) 命令に遭遇すると、パイプラインをクリアしてリロードする必要があるため、時間がかかります。速度を最適化する際の 1 つの目的は、命令パイプラインへのリロードの回数を減らすことです。これは、分岐命令を減らすことを意味します。

他の人がSOで述べているように、速度とプロファイルの最適化を設定してコードをコンパイルしてください。私は、アセンブリ言語のリスト (コンパイラから出力されたもの、またはデバッガで表示されたもの) も参照することを好みます。これをベースラインとして使用します。プロファイリングできない場合は、アセンブリ命令のカウントを概算として使用できます。

次のステップは、ブランチの数を減らすことです。または分岐が行われた回数。ループを展開すると、分岐の回数を減らすことができます。インライン化は、分岐の数を減らすのに役立ちます。この微調整手法を適用する前に、設計とコードの実装を見直して、分岐を減らすことができるかどうかを確認してください。たとえば、ブール演算またはカルノー マップを使用して、"if" ステートメントの数を減らします。私のお気に入りは、要件を減らし、実行する必要のないコードを排除することです。

コードの実装で、変更されないコードをfororwhileループの外に移動します。一部のループは、方程式に縮小される場合があります (たとえば、加算のループを乗算に置き換えます)。また、「このループは本当に何回実行する必要がある のか​​」と尋ねて、反復の量を減らします)。

もう 1 つの手法は、データ指向設計を最適化することです。こちらのリファレンスもチェックしてください。

最適化の制限を設定することを忘れないでください。ここで、これ以上最適化しても ROI や顧客満足度が向上しないと判断します。また、段階的に最適化を適用します。これにより、マネージャーが要求したときに成果物を作成できます。

于 2010-05-04T22:36:49.650 に答える
1

コードでプロファイラーを実行します。どこで時間を過ごしているかを推測しているだけなら、おそらく間違っています。プロファイラーは、どの関数が最も時間がかかっているかを示し、それに集中することができます。関数呼び出し自体よりも時間がかかる関数で何かをしている可能性があります。浮動小数点演算を整数に、または整数演算をシフトに変更できるかどうかを調べましたか? 大した違いがないものをいじるのに多くの時間を費やすことができます。コードでプロファイラーを実行し、変更内容が違いを生むことを確認してください。

于 2010-05-04T20:10:28.857 に答える
0

関数とインラインについては、残念ながら簡単な答えはありません。つまり、依存します。この FAQを参照してください。「for」と「while」では、パフォーマンスに大きな違いはないと思います。

于 2010-05-04T20:01:42.803 に答える
0

一般に、関数呼び出しにはインライン化よりも多くのオーバーヘッドが必要です。ただし、これはコンパイラ (特にコンパイル/最適化設定) によってかなり影響を受ける可能性があるため、プロファイルを作成する必要があります。たとえば、一部のコンパイラはコードを自動的にインライン化します。

于 2010-05-04T22:41:09.747 に答える