GCC のさまざまな最適化レベルの違いは何ですか? デバッグ フックを使用する必要がないと仮定すると、利用可能な最高レベルの最適化を使用しないのはなぜでしょうか? より高いレベルの最適化は、より高速なプログラムを必然的に (つまり、証明可能に) 生成しますか?
4 に答える
はい、レベルが高いほど、プログラムのパフォーマンスが向上する場合があります。ただし、コードによっては問題が発生する可能性があります。たとえば、分岐予測 (-O1 以上で有効化) は、競合状態を引き起こすことによって、不適切に作成されたマルチスレッド プログラムを中断させる可能性があります。最適化は実際には、あなたが書いたものよりも良いものを決定しますが、場合によってはうまくいかないかもしれません。
また、より高い最適化 (-O3) を行っても、合理的なメリットはなく、サイズが大幅に増える場合があります。このサイズのトレードオフがシステムのパフォーマンスを合理的に向上させるかどうかは、独自のテストで判断できます。
最後に、GNU プロジェクトはすべてのプログラムをデフォルトで -O2でコンパイルします。-O2 は他の場所ではかなり一般的です。
一般に、より高い最適化レベル-O2
( -O3
gcc の場合のみですが、他のコンパイラにはより高いレベルがあります) には、コードのサイズを大きくする可能性のある最適化が含まれます。-O3
これには、ループのアンローリング、大量のインライン化、サイズに関係なくアラインメントのためのパディングなどが含まれます。他のコンパイラーは、正確さを犠牲にして速度を大幅に向上させる特定の最適化と同様に、ベクトル化および より高いレベルでのプロシージャー間の最適化を提供します。(たとえば、高速で精度の低い計算ルーチンを使用するなど)。これらのものを使用する前に、ドキュメントを確認してください。
パフォーマンスに関しては、それはトレードオフです。一般に、コンパイラの設計者は、コードのパフォーマンスを低下させないようにこれらのことを調整しようとします。したがって、-O3
通常は (少なくとも私の経験では) 役立ちますが、マイレージは異なる場合があります。非常に積極的なサイズ変更の最適化がパフォーマンスを向上させるとは限りません (たとえば、非常に積極的なインライン化はキャッシュ汚染を引き起こす可能性があります)。
さまざまな最適化レベルに関する情報を含むWeb ページを見つけました。どこかで聞いた覚えのあることの 1 つは、最適化によって実際にプログラムが壊れる可能性があり、それが問題になる可能性があるということです。しかし、もはやそれがどれほどの問題であるかはわかりません。おそらく、今日のコンパイラは、これらの問題を処理するのに十分なほどスマートです。
サイドノート:
さまざまなバージョンやプラットフォームで、gcc コマンド ラインのグローバル ディレクティブによってどのフラグが有効になるかを正確に予測することは非常に困難-O
です。また、GCC サイトのすべてのドキュメントは、すぐに古くなる可能性が高いか、コンパイラの内部について十分に詳しく説明していません。 .
-O
フラグの 1 つと他の-f
フラグ、および/またはそれらの組み合わせを使用したときに、特定のセットアップで何が起こるかを正確に確認する簡単な方法を次に示します。
- 空のソース ファイルをどこかに作成します。
touch dummy.c
-O
通常使用するすべての、-f
および/または-m
フラグを使用して、通常と同じようにコンパイラ パスを使用して実行しますが-Q -v
、コマンド ラインに追加します。gcc -c -Q -v dummy.c
- 生成された出力を検査し、おそらく別の実行のために保存します。
- コマンド ラインを好みに合わせて変更し、生成されたオブジェクト ファイルを削除して
rm -f dummy.o
再実行します。
また、純粋主義者の観点から、ほとんどの重要な最適化は「壊れた」コードを生成することを常に念頭に置いてください (壊れたコードは、コーナーケースで最適なパスから逸脱することとして定義されます)。最適化メカニズムのセットは、コンパイラ出力の正確さのレベルを選択することに要約される場合があります。どのコンパイラのオプティマイザにも常に (そして現在も) バグがあります。いくつかのサンプルについては、GCC メーリング リストと Bugzilla を確認してください。コンパイラの最適化は、実際に測定を実行した後にのみ使用する必要があります。
- より良いアルゴリズムを使用することによる利益は、コンパイラーの最適化による利益よりも小さくなります。
- ブルームーンで毎回実行されるコードを最適化しても意味がありません。
- オプティマイザーがバグを導入した場合、コードの実行速度は重要ではありません。