Vermutlich handelt es sich nicht wirklich um einen Bug, aber dennoch um
einen sehr sonderbaren Effekt: Mit Optimierung -O3 kann der erzeugte
Code riesengross werden, bzw. wesentlich grösser als ohne Optimierung!
Bei einem kleinem Testprogramm:
-O0 574 Bytes
-O1 392 Bytes
-O2 390 Bytes
-O3 4850 Bytes!
-Os 386 Bytes
Woran kann das liegen?
Test-Programm
Peter S. schrieb:
> Vermutlich handelt es sich nicht wirklich um einen Bug, aber dennoch um> einen sehr sonderbaren Effekt: Mit Optimierung -O3 kann der erzeugte> Code riesengross werden, bzw. wesentlich grösser als ohne Optimierung!
Ja, -O3 ist letztlich sowas wie ``optimize for speed''. Da werden
Schleifen entrollt, Funktionen inline expandiert etc. pp. was das
Zeug hält.
Was sagt denn das Assembler-Listing?
Wenn O3 eine Geschwindigkeitsoptimierung ist (kenne die
Compiler-Optionen nicht gut), tippe ich auf ein partielles
loop-unrolling im main-Programm
http://de.wikipedia.org/wiki/Hotspot-Optimierung#Loop-Unrolling
Einfach ein Schuss ins Blaue.
Schöne Grüße,
Kai
Das würde ich gernerell so nicht unterschreiben. Wenn dein Prog extrem
zeitkritisch ist, könnten dir genau das den erhofften Erfolg bringen,
dein Controller hätte ja genug Flash. ;-)
Aber im Allgemeinen funktioniert O2 eigentlich am besten (meine
Erfahrung)
Gruß
Fabian
Jo, -O123 sind normalerweise für Geschwindigkeit, -Os für Programmgröße.
Wenn noch Programmspeicher übrig ist, ruhig mal die höchste
Optimierungsstufe ausprobieren (trotzdem sauber programmieren!) --
ungenutzten Flash-Speicher kann man nämlich in der Regel nicht mehr im
Geschäft zurückgeben oder umtauschen...
Jede Optimierung kann nach hinten los gehen.
Ob eine Optimierung wirklich diesen Namen verdient, ist immer auch
abhängig von der Zielarchitektur.
Einfach mal bedenken, daß die Voreinstellungen der aktivierten
Optimierungsstrategien in avr-gcc die gleichen sind wie für 32- und
64-Bit Systeme auch!
Und da AVR nun mal weder Date- noch Codecache hat, keine Pipeline
(zumindest ist die Dauer von Befehlsausführungen unabhängig von deren
Anordnung), Sprünge recht billig sind, manche Arithmetik jedoch
vergleichsweise teuer (zB a << n, a/b, a%b) passt das eben bei weitem
nicht immer. Nur daß der Code reisengroß wird, heisst nicht, daß er
schneller wird ;-)
Es vergrößern sich zum Beispiel Sprungweiten. Während in kompaktem Code
oft ein relativer, Sprung genommen werden kann, muss bei ausladendem
Code die Bedingung umgedreht werden (kostet nix), und über einen
absoluten Sprung gesprungen werden, welcher das eigentliche Sprungziel
adressiert. Das ist langsamer und breiter. Wenn eine aufgerolle Schleife
dann zig solcher Konstrukte enthält (Schleifenbedingung, break, ...),
schiesst sich die Optimierung selbst ins Knie...
Unangenehm ist auch, daß viele Optimierungen die Lebensdauer von
Registern erhöhen (zB loop invariant motion etc). Das macht den Code
theoretisch schneller, aber wenn die Register ausgehen und stattdessen
die Werte zum RAM hin- und hergeschaufelt werden müssen, ist der Code
deutlich größer und merklich langsamer. Der Effekt lässt sich hin und
wieder auch bei Inlining beobachten.
Um Gefühl defür zu bekommen, welche Optimierung geeignet ist, hilft nur
eins: Hin und wieder muss man sich die Compilerausgabe anschauen.
Irgendwann hat man dann raus, was in 90% der Fälle gut taugt. -O3 gehört
für avr-gcc aber sehr wahrscheinlich nicht dazu.
Die einzigen Änderungen, die avr-gcc an den Optionen vornimmt, sind
Sven P. schrieb:
> Jo, -O123 sind normalerweise für Geschwindigkeit, -Os für Programmgröße.
Wobei das mit der Geschwindigkeit beim AVR schnell nach hinten losgehen
kann, -Os ist oft auch am schnellsten.
Außerdem arbeiten die Optimierungen mit der Brechstange, d.h. es wird
alles gleich optimiert, egal, ob alle 10 Tage aufgerufen oder alle 10µs.
Man kann also leicht Verzehnfachung des Codes erreichen bei 0%
Geschwindigkeitszuwachs.
Andere Optimierungen neben -Os würden nur Sinn machen, wenn man sie
selektiv anwenden könnte (im Sourcecode auf einzelnen Funktionen).
Peter
Peter Dannegger schrieb:
> Wobei das mit der Geschwindigkeit beim AVR schnell nach hinten losgehen> kann, -Os ist oft auch am schnellsten.
Würd ich auch empfehlen als Grundlage.
> Andere Optimierungen neben -Os würden nur Sinn machen, wenn man sie> selektiv anwenden könnte (im Sourcecode auf einzelnen Funktionen).
Das geht ab 4.4.0 per
Peter Dannegger schrieb:
> Sven P. schrieb:>> Jo, -O123 sind normalerweise für Geschwindigkeit, -Os für Programmgröße.>> Wobei das mit der Geschwindigkeit beim AVR schnell nach hinten losgehen> kann, -Os ist oft auch am schnellsten.
Klar.
Peter Dannegger schrieb:
> Außerdem arbeiten die Optimierungen mit der Brechstange, d.h. es wird> alles gleich optimiert, egal, ob alle 10 Tage aufgerufen oder alle 10µs.
Nicht grundsätzlich, GCC kann Laufzeitergebnisse des Profilers gprof bei
der Optimierung berücksichtigen. Nur leider gibt's gprof nicht für den
AVR. Wäre ein lustiges Projekt etwas ähnliches für den AVR zu
implementieren, ob's bei der Optimierung viel bringt sei mal
dahingestellt.