18

私は ARM デバイスで拡張現実用の C++ コードを開発してきましたが、良好なフレーム レートを維持するには、コードの最適化が非常に重要です。効率を最大限に高めるためには、コンパイラの作業を楽にし、プログラムのサイクル数を減らすための一般的なヒントを収集することが重要だと思います。どんな提案でも大歓迎です。

1-高コストの命令を避ける: 除算、平方根、sin、cos

  • 論理シフトを使用して、2 で除算または乗算します。
  • 可能であれば、逆数を掛けます。

2-内部の「for」ループを最適化します。これらはボトルネックであるため、特に除算や平方根など、内部で多くの計算を行うことは避ける必要があります。

3-いくつかの数学関数 (sin、cos、...) のルックアップ テーブルを使用します。

便利なツール

  • objdump: コンパイルされたプログラムのアセンブリ コードを取得します。これにより、2 つの関数を比較して、本当に最適化されているかどうかを確認できます。
4

2 に答える 2

19

C++ コードを ARM 用に最適化する際の一般的なルールに関する質問に答えるために、いくつかの提案を示します。

1) おっしゃる通り、除算命令はありません。可能であれば、論理シフトを使用するか、逆数を掛けます。
2) メモリは CPU の実行よりもはるかに低速です。論理演算を使用して、小さなルックアップ テーブルを回避します。
3) 書き込みバッファを最大限に活用するために、一度に 32 ビットを書き込むようにします。short や char を記述すると、コードの速度が大幅に低下します。つまり、小さいビットを論理 OR して DWORD として書き込む方が高速です。
4) L1/L2 キャッシュ サイズに注意してください。原則として、ARM チップのキャッシュは Intel よりもはるかに小さいです。
5) 可能な場合は SIMD (NEON) を使用します。NEON 命令は非常に強力で、「ベクトル化可能な」コードでは非常に高速です。NEON 組み込み関数は、ほとんどの C++ 環境で使用でき、手動で調整された ASM コードを記述するのとほぼ同じ速度で実行できます。
6) キャッシュ プリフェッチ ヒント (PLD) を使用して、ループ読み取りを高速化します。ARM には、最新の Intel チップのようにスマートなプリキャッシュ ロジックがありません。
7) コンパイラが優れたコードを生成することを信用しないでください。ASM の出力を見て、ASM のホットスポットを書き換えます。ビット/バイト操作の場合、C 言語は ASM で実現できるほど効率的に物事を指定できません。ARM には、強力な 3 オペランド命令、マルチロード/ストア、および「フリー」シフトがあり、コンパイラが生成できるものよりも優れています。

于 2012-05-29T16:27:18.810 に答える
17

アプリケーションを最適化する最善の方法は、優れたプロファイラーを使用することです。効率を考えてコードを書くことは常に良い考えですが、コードが遅いかもしれないと「思う」ところに変更を加えるのも避けたいでしょう。

ボトルネックがどこにあるかを見つけ出し、それらに焦点を当てます。

私にとって、プロファイリングは反復プロセスです。通常、1 つのボトルネックを修正すると、重要度の低い他のボトルネックが明らかになるためです。

SW のプロファイリングに加えて、利用可能な HW プロファイリングの種類を確認します。キャッシュ ミス、メモリ バス アクセスなど、さまざまなハードウェア メトリックを取得できるかどうかを確認します。これは、メモリ バスまたはキャッシュがボトルネックになっているかどうかを知るのにも非常に役立ちます。

私は最近、この同様の質問をして、いくつかの良い答えを得ました:影響の少ない c++ プロファイラーを探しています

于 2012-05-29T13:44:03.397 に答える