web-dev-qa-db-ja.com

何が速いですか?複数の変数または単一の配列?

マイクロコントローラーで非常に長い計算を実現するCコードの関数があります。現時点では速度を最適化するようにしています。関数のコンテンツはMathematicaを使用して自動的に作成されます。何百もの計算があり、次のようになります。

void calcResult(float *result, float arg1, float arg2, ... float argN){
   float tmp1 = arg1 * 2 + arg2;
   float tmp2 = tmp1/arg3 + tmp1;
   ...
   ...
   float tmpN = tmp320 + tmp15 * 2;
   *result = tmp2 + tmpN;
}

「tmp」変数ではなく「tmp」変数の数と同じサイズの配列を使用する方が速いか、または別の方法でそのような関数の速度を上げることができるかどうかを自問しました(仮定では、 「結果」を得るための計算は、必要な計算時間の観点からすでに「最適化」されていますか?

編集:

私の意見では コーディング時にマイクロ最適化は重要ですか? 目標がコードの最適化でもある場合でも、特定の質問に答えることはできません。

2
theNewOne

いつものように、最終的な答えはprofileの両方のアプローチであり、経験的な結果によって決定されます。ただし、最新のCコンパイラテクノロジを考えると、速度の違いは期待できません。コンパイラーの手を2つの方法で結び付けているため、コードを遅くすることさえできます。

  1. 変数がスタックに表示される特定の順序を指示している(配列がスタックに割り当てられていると想定)
  2. (レジスターやスピルではなく、スタック上の)一時的な特定のストレージ場所を指示している

コンパイラがこれを理解できる可能性は高いですが(LLVMの Mem2Reg passを参照)、コンパイラに意味を伝えないのはなぜですか?コンパイラーは、ソフトウェアのパイプライン処理とレジスターの割り当て(およびスタックの局所性)を自由に決定できます。

コンパイラーがそれ自体で推測できる場合でも、コードジェネレーターのデバッグに役立つため、すべての一時変数を宣言することをお勧めしますconst

4
Alex Reinking

これらの条件が満たされた場合:

  • 配列はローカルです(関数スコープに限定されます)
  • アレイはローカルでのみ使用されます
  • 配列の構造(ポインタ、参照、型など)に関する情報が、(関数呼び出しまたはストアを介して)別の関数にリークされていない。
  • その他...(コンパイラの最適化の経験がないため、私は間違っている可能性があります)

コンパイラーは、集約(SRA、SRoA)のスカラー置換を適用する場合があります。これは、ローカル配列(要素ごとに単一の割り当て方法で使用される)アプローチとローカル変数アプローチが同じ方法で最適化され、何百ものスタックスペースを必要としない場合があることを意味します。 float要素または変数の。

これが当てはまるかどうかを確認するには、最適化されたビルドからの逆アセンブリを確認する必要があります。コンパイラがSRAを適用できない要因がある可能性があります。

SRAが実行されない場合、アレイアプローチに大きな問題があります。これは、関数が数百のfloat変数(配列のサイズ)に十分なスタックスペースを予約することを意味します。これは、配列を「削除」できないと判断したためです。これをローカルスカラー変数のアプローチと比較すると、コンパイラーがそれらをレジスターにローテーションしてメモリーに戻し、すでに期限切れまたは使用されていない値のメモリーを再利用できます。

ここでも、最適化されたビルドと最適化されていないビルドの両方から逆アセンブリを確認することを強くお勧めします。あなたは何かを学ぶでしょう。学校ではコンパイラの理論や最適化を学びませんでした。これらのトピックについて私が学んだことのほとんどは、長年コンパイラが生成した逆アセンブリを読んだり、専門家が書いた記事をオンラインで読んだりしたことから来ています。

関数もインライン化される場合があります。その場合、その最適化の結果は、呼び出し元の記述方法にも依存します。

2
rwong

他の人がすでに指摘したように、私はあなたの提案された変更の影響に関して私の期待が高すぎるとは思わないでしょう。最善の策は、必ずしも順番に実行する必要のない計算トラックを見つけて、別のスレッドで実行させることです。これにより、パフォーマンスが著しく向上する可能性があります。

ただし、例を見ると、すべてのステップで前のステップの結果が必要であるため、この特定のケースでは実行可能なオプションとは思えません。

0
Martin Maat