wake-up-neo.com

GCC: Unterschied zwischen -O3 und -Os

Ich bin mit GCC -O3-Flag gut vertraut, aber wie unterscheidet es sich von -Os? In welcher Situation sollten wir eine gegenüber der anderen bevorzugen?

21
Saqlain

Die GCC-Dokumentation beschreibt, was diese Optionen sehr explizit tun.

-O3 versucht, den Code sehr stark für die Leistung zu optimieren. Es beinhaltet alle Optimierungen, die -O2 beinhaltet, sowie einige weitere.

-Os hingegen weist GCC an, "die Größe zu optimieren". Es aktiviert alle -O2-Optimierungen , die die Größe der ausführbaren Datei nicht erhöhen, und schaltet auch einige Optimierungsflags um, um die Größe der ausführbaren Datei weiter zu reduzieren.

Beachten Sie, dass ich bei meinen Beschreibungen absichtlich etwas vage war. In der GCC-Dokumentation finden Sie eine ausführlichere Diskussion darüber, welche Flags für beide Optimierungsstufen aktiviert sind.

Ich glaube, dass die -O * -Optimierungsniveaus genau das sind - sich gegenseitig ausschließende Ebenen der Optimierung. Es ist nicht wirklich sinnvoll, sie zu mischen, da zwei Ebenen Flaggen aktivieren oder weglassen, die die andere absichtlich weglässt oder aktiviert (bzw. aktiviert). Wenn Sie mischen und zusammenpassen möchten (Sie möchten dies wahrscheinlich nicht wirklich tun, es sei denn, Sie haben einen wirklich guten Grund, bestimmte Flags zu verwenden), lesen Sie am besten die Dokumentation und mischen und passen Sie die Flags in jedem Level an ermöglicht von hand.

Ich denke, ich werde auch diesen Artikel aus dem Gentoo Linux Wiki verlinken, in dem es um Optimierungsflags geht, die sich auf das Erstellen der Pakete für das Betriebssystem beziehen. Natürlich ist dies nicht alles anwendbar, aber es enthält immer noch einige interessante Informationen - zum einen:

Das Kompilieren mit -O3 ist keine garantierte Möglichkeit, die Leistung zu verbessern, und in vielen Fällen kann ein System aufgrund größerer Binärdateien und erhöhter Speicherauslastung verlangsamen. -O3 ist auch dafür bekannt, mehrere Pakete aufzubrechen. Daher wird die Verwendung von -O3 nicht empfohlen.

Laut diesem Artikel ist -O2 meistens "so gut wie" -O3 und hinsichtlich der fehlerhaften ausführbaren Ausgabe sicherer zu verwenden.

25
CmdrMoozy

Ich schlage vor, die GCC-Dokumentation zu lesen. -O3 dient zum Abrufen eines schnell ausgeführten Codes (auch auf Kosten einiger Code-Bloat), während -Os die Größe des generierten Codes optimiert.

Es gibt Tonnen von anderen (dunklen) GCC Optimierungsflags (z. B. -fgcse-sm), von denen viele selbst bei -O3 nicht aktiviert sind.

Möglicherweise interessieren Sie sich auch für die Verwendung von -flto (für Link-Time Optimization), zusätzlich zu z. -O3 oder -Os, sowohl zur Kompilierzeit als auch zur Zeit von link. Dann sehen Sie auch diese Antwort .

Achten Sie schließlich darauf, die neueste Version von GCC (derzeit 4,8 Ende 2013) zu verwenden, da GCC seine Optimierungen erheblich verbessert.

Möglicherweise möchten Sie auch -mtune = native (zumindest für x86) verwenden.

Sie können sogar einen eigenen Optimierungspass schreiben, der für Ihre eigenen Bibliotheken und APIs spezifisch ist, möglicherweise mithilfe von MELT plugin.

Wie CmdrMoozy antwortete möchten Sie vielleicht -O2 statt -O3 verwenden (beachten Sie jedoch, dass die letzten GCC-Versionen ihren -O3 stark verbessert haben, so dass die Gentoo - Empfehlung gegen -O3 und zugunsten von -O2 weniger relevant wird. ).

Wie dieses SlashDot-ed Stack-Papier (von Xi Wang, Nickolai Zeldovich, M. Frans Kaashoek und Armando Solar-Lezama) zeigt, sind viele Programme nicht vollständig C-konform und nicht glücklich (und verhalten sich nicht korrekt) ) wenn einige valid - Optimierungen durchgeführt werden. Undefiniertes Verhalten ist ein heikles Thema.

Übrigens, beachten Sie, dass die Verwendung von -O3 normalerweise die Kompilierungszeit viel länger macht und oft (aber nicht immer) höchstens einige Prozent mehr Leistung bringt als -O2 oder sogar -O1.... (mit -flto ist es sogar noch schlimmer). Aus diesem Grund verwenden I es selten.

Es hängt davon ab, ob. Müssen Sie Geschwindigkeit oder Größe optimieren? 

-O3
Noch mehr optimieren. -O3 aktiviert alle durch -O2 angegebenen Optimierungen und aktiviert auch die -finline-Funktionen, -funswitch-loops, -vorhersagende-Commoning-, -fgcse-after-reload-, -tree-loop-vectorize-, -tree-slp-vectorize-, -fvect-cost-model-, -tree-partielle-pre- und -fipa-cp-Klonoptionen 

-O0
Reduzieren Sie die Kompilierungszeit und sorgen Sie dafür, dass das Debuggen die erwarteten Ergebnisse liefert. Dies ist die Standardeinstellung. 

-Os
Für Größe optimieren. -Os aktiviert alle -O2-Optimierungen, die normalerweise die Codegröße nicht erhöhen. Es führt auch weitere Optimierungen durch um die Codegröße zu reduzieren.
-Os Deaktiviert die folgenden Optimierungsflags:

-falign-functions-falign-jumps-falign-loops-falign-labels-freorder-blocks-freorder-blocks-and-partition-fprefetch-loop-arrays

http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html

Tatsächlich ist -O eine Abkürzung für eine lange Liste unabhängiger Optimierungen. Wenn Sie nicht wissen, was Sie brauchen, entscheiden Sie sich für -O3.

2
opalenzuela

-O3 optimiert die Geschwindigkeit, -Os optimiert den Platz. Das bedeutet, dass Sie mit -O3 eine schnelle ausführbare Datei erhalten, die aber relativ groß sein kann und mit -Os eine kleinere ausführbare Datei.

Raum- und Zeiteffizienz ist in der Regel ein Kompromiss. Schnellere Algorithmen beanspruchen in der Regel mehr Speicherplatz, während eingebaute Algorithmen (Algorithmen, die den Speicherplatzbedarf nicht erhöhen) weniger effizient sind.

Normalerweise haben moderne Computer viel Speicherplatz, daher ist -O3 normalerweise vorzuziehen. Wenn Sie jedoch etwas mit Low-Ram (wie ein kleines Gerät) programmieren, bevorzugen Sie -Os

0
Nathan