私は GCC の -O3 フラグに精通していますが、-Os とどのように違うのでしょうか。
5 に答える
GCCのドキュメントでは、これらのオプションが何をするのかを非常に明確に説明しています。
-O3 は、パフォーマンスのためにコードを非常に最適化しようとします。-O2 に含まれるすべての最適化に加えて、さらにいくつかの最適化が含まれています。
一方、-Os は GCC に「サイズを最適化する」ように指示します。実行可能ファイルのサイズを増加させないすべての -O2 最適化を有効にし、いくつかの最適化フラグを切り替えて、実行可能ファイルのサイズをさらに縮小します。
意図的に説明を少し曖昧にしてあることに注意してください。どちらの最適化レベルでもどのフラグが有効になるかについての詳細な説明については、GCC のドキュメントを参照してください。
-O* 最適化レベルは、相互に排他的で異なるレベルの最適化であると私は信じています。2 つのレベルでフラグが有効または除外され、もう一方のレベルで意図的に除外または有効にされているため (それぞれ)、それらを混在させることはあまり意味がありません。混ぜ合わせたい場合 (特定のフラグのセットが必要な本当に正当な理由がない限り、実際にはやりたくないでしょう)、ドキュメントを読み、各レベルのフラグを混ぜ合わせて一致させることをお勧めします。手で有効にします。
Gentoo Linux Wiki からのこの記事もリンクすると思います。この記事では、オペレーティング システムのパッケージのビルドに関連する最適化フラグについて説明しています。明らかに、これのすべてが当てはまるわけではありませんが、いくつかの興味深い情報が含まれています。
-O3 を指定してコンパイルしても、パフォーマンスが向上する保証はありません。実際、多くの場合、バイナリが大きくなり、メモリ使用量が増加するため、システムの速度が低下する可能性があります。-O3 は、いくつかのパッケージを壊すことでも知られています。したがって、-O3 の使用はお勧めしません。
その記事によると、-O2 は、ほとんどの場合、-O3 と「同等」であり、壊れた実行可能出力に関しては、より安全に使用できます。
GCC のドキュメントを読むことをお勧めします。-O3-Os
は、生成されたコードのサイズを最適化しながら、高速に実行されるコードを取得するためのものです (コードの肥大化を犠牲にしても) 。
他にも (不明瞭な) GCC最適化フラグがたくさんあります(例: など-fgcse-sm
) -O3
。
コンパイル時とリンク時の両方で、 eg orに加えて-flto ( Link-Time Optimization用) を使用することにもおそらく興味があるかもしれません。次に、この回答も参照してください。-O3
-Os
最後に、GCC は最適化を大幅に改善しているため、GCC の最新バージョン (2013 年末時点で現在 4.8) を使用するように注意してください。
-mtune=nativeも使用することをお勧めします(少なくとも x86 の場合)。
また、おそらくMELTプラグインを使用して、独自の特定のライブラリと API に固有の独自の最適化パスを作成することもできます。
CmdrMoozy が答えたように、 -O2
overを使用することを好むかもしれません-O3
(ただし、最近の GCC バージョンでは が大幅に改善されていること-O3
に注意してください。-O3
-O2
また、この SlashDot-ed Stack 論文(Xi Wang、Nickolai Zeldovich、M. Frans Kaashoek、および Armando Solar-Lezama による) が示すように、多くのプログラムは完全に C 標準に準拠しておらず、一部が有効な場合に満足できません (そして正しく動作しません)。最適化が行われます。未定義の動作は扱いにくいテーマです。
ところで、通常、 を使用するとコンパイル時間が大幅に長くなり、多くの場合 (ただし、常にではありません)、または....-O3
よりもパフォーマンスが最大で数パーセント向上することに注意してください( を使用するとさらに悪化します)。これが私がほとんど使用しない理由です。-O2
-O1
-flto
場合によります。速度やサイズを最適化する必要がありますか?
-O3
さらに最適化します。-O3 は、-O2 で指定されたすべての最適化をオンにし、-finline-functions、-funswitch-loops、-fpredictive-commoning、-fgcse-after-reload、-ftree-loop-vectorize、-ftree-slp-vectorize もオンにします、-fvect-cost-model、-ftree-partial-pre、および -fipa-cp-clone オプション。-O0
コンパイル時間を短縮し、デバッグで期待どおりの結果が得られるようにします。これがデフォルトです。-Os
サイズを最適化します。-Os は、通常はコード サイズを増加させないすべての -O2 最適化を有効にします。また、コード サイズを削減するために設計されたさらなる最適化も実行します。
-Os 次の最適化フラグを無効にします。
-falign-functions
-falign-jumps
-falign-loops
-falign-labels
-freorder-blocks
-freorder-blocks-and-partition
-fprefetch-loop-arrays
実際、-Oは、独立した最適化の長いリストの省略形です。何が必要かわからない場合は、-O3を選択してください。
-O3 は速度を最適化し、-Os はスペースを最適化します。つまり、 -O3 は高速な実行可能ファイルを提供しますが、かなり大きくなる可能性があり、 -Os はより小さな実行可能ファイルを提供しますが、遅くなる可能性があります。
通常、スペースと時間の効率はトレードオフです。より高速なアルゴリズムはより多くのスペースを占有する傾向があり、インプレース アルゴリズム (スペースの使用量を増加させないアルゴリズム) は効率が低下する傾向があります。
通常、最新のコンピュータには十分なメモリ空間があるため、通常は -O3 が推奨されます。ただし、RAM が小さいもの (小さなデバイスなど) をプログラミングしている場合は、-Os を使用することをお勧めします。
これに答えるのは実際には不可能です。単純なルールは、クリティカル コード パスの速度を最適化し、ロードなどの非クリティカル コード パスのサイズを最適化することです...
一部のコンパイラは、2 つのパスで動作して決定を下すことができます。最初のパスはプロファイリングをサポートする特別な実行可能ファイルを作成し、アプリケーションを実行してデータを収集し、2 番目のコンパイルはデータに基づいて最適なものを決定できます。非仮想化、分岐予測などを可能にします...