Forum: Compiler & IDEs GCC Compiler: Optimierung ein oder aus?


von Christian J. (elektroniker1968)


Lesenswert?

Hallo,

ich habe festgestellt, dass sich ein 40kb projekt mal eben auf 20k 
reduziert, wenn man Stufe 1,2,3 einschaltet. Das kann doch irgendwie 
nicht sein?

Stellt sich die allgemeine Frage: Sollte man oder besser nicht? Was 
fängt man sich damit ein?

Gruss,
Christian

von ... (Gast)


Lesenswert?


von Jan M. (mueschel)


Lesenswert?

Zusammengefasst: Einschalten! -O2 dürfte in den meisten Fällen die 
geeignete Wahl sein. Fehler durch die Optimierung sind in praktisch 
allen Fällen Fehler im eigenen Code. Insbesondere die delay-Funktionen 
funktionieren nur mit Optimierung.

von Andreas K. (a-k)


Lesenswert?

-Os käme auch in Frage.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Und dran gewöhnen, dass der Codefluss bei Debuggen nicht so
geradlinig ist, wie man ihn aufgeschrieben hat.  Variablen, die
der Programmierer für das Verständnis bzw. die Überschaubarkeit
des Codes eingeführt hat, braucht der Compiler auch nicht
zwangsläufig 1:1.

von Rolf Magnus (Gast)


Lesenswert?

> ich habe festgestellt, dass sich ein 40kb projekt mal eben auf 20k
> reduziert, wenn man Stufe 1,2,3 einschaltet. Das kann doch irgendwie
> nicht sein?

Warum nicht? Optimierung ist dazu da, um den Code ressourcensparender zu 
machen. Das ist hier der Fall.

> Stellt sich die allgemeine Frage: Sollte man oder besser nicht?

Warum nicht?

> Was fängt man sich damit ein?

??

von Martin Thomas (Gast)


Lesenswert?

Als Ergänzung zu möglichen Problemen, wenn man die Optimierung vorher 
noch nie genutzt hat: ein "vergessenes" volatile (vgl. avr-libc FAQ#1) 
macht sich sehr wahrscheinlich erst bei eingeschalteter Optimierung 
durch Fehlerverhalten in der Anwendung bemerkbar. Aber wie von Jan M. 
schon angemerkt: die Ursache ist dabei unzulänglicher Anwendercode 
(=etwas "vergessen") und nicht der Compiler, denn der macht was ihm 
aufgetragen wurde: möglicht gut optimieren, also u.a. Speicherzugriffe 
vermeiden und in Registern "cachen".

von Christian J. (elektroniker1968)


Lesenswert?

Hallo,

wo wir beim Thema optimieren sind: Wie kann ich nach Fertigstellung 
eines Projektes mit dem ARM7 herausfinden, wieviel Stack tatsächlich 
genutzt wird? Bei mir stehen beim Linker die Werte standardmässig 
eingestellt, denke jedoch, dass man durch passgenaues Setzen mehr 
Speicher freimachen kann.

von yalu (Gast)


Lesenswert?

> Wie kann ich nach Fertigstellung eines Projektes mit dem ARM7
> herausfinden, wieviel Stack tatsächlich genutzt wird?

Genaue, aber schwierige  Methode:

Anhand des generierten Assemblercodes herausfinden, wann das Programm
wieviel Bytes Daten auf den Stack schiebt bzw. in Form lokaler
Variablen nutzt. Dann durch eine Analyse des Programmflusses
(verschachtelte Funktionsaufrufe) herausfinden, wann der Stack maximal
benutzt wird. Dann die Stacknutzung zu diesem Zeitpunkt abzählen.

Einfache, aber ungenaue Methode:

Stack zunächst großzügig dimensionieren. Beim Programmstart den
gesamten Stackbereich mit "magic Numbers" füllen. Programm längere
Zeit laufen lassen, dabei darauf achten, dass möglichst alle
Verzweigungen des Programmflusses auch tatsächlich auftreten (auch
innerhalb von Bibliotheksfunktionen). Dann die Bytes auf dem Stack,
die nicht mehr die magic Number enthalten, abzählen. Es kann leider
nicht immer garantiert werden, dass während des Programmlaufs auch
tatsächlich der stackmäßige worst Case eintritt.

von Bernhard R. (barnyhh)


Lesenswert?

Leute, knausert nicht mit dem Stack rum! Stack-Overflows gehört zu den 
ekelhaftesten und am schwersten zu findenden Problemen. Sie treten im 
übrigen meist erst nach Ende der DEBUG-Phase auf.

Ein Beispiel zu dem Thema:
Vor vielen Jahren wurde in Hamburg ein neues Stellwerk in Betrieb 
genommen. Die Software dieses Stellwerks fiel durch Stack-Overflow alle 
paar Tage mal aus, meist im Berufsverkehr. Das Ganze ging so weit, daß 
das Stellwerk ausgeschaltet und durch den Vorgänger ersetzt wurde.

Erst Monate später war der Stack-Overflow gefunden, und das neue 
Stellwerk ging erneut in Betrieb.

Bernhard

von Falk B. (falk)


Lesenswert?

@ Bernhard R. (barnyhh)

>Leute, knausert nicht mit dem Stack rum! Stack-Overflows gehört zu den
>ekelhaftesten und am schwersten zu findenden Problemen. Sie treten im

Frage. Kann man nicht als Option eine Laufzeitprüfung des Stacks 
einbauen? Klar kostet das Performance, das ist aber in vielen Fällen 
unkritisch. Zu Debugzwecken ist es Gold wert.

MfG
Falk

von Martin Thomas (Gast)


Lesenswert?

Kann man. Wenn richtig erinnert, bietet der IAR-EWARM eine Option dafür. 
Beim GNU-compiler ist das auch vorgesehen (mapcs-stack-check, Limit in 
SL). Selbst aber noch nicht erfolgreich ausprobiert. Bin nichtmal 
wirklich sicher, ob die Funktionalität beim arm-gcc implementiert ist. 
Kommandozeilenparameter gibt es zwar, in der Dokumentation von 4.2.1 
finde ich im Moment garnichts mehr dazu.

von Bernhard R. (barnyhh)


Lesenswert?

@ Falk

Die Sache mit den Laufzeitprüfungen ist wunderschön und gut, aber ...
- Der "Performancefetischismus" selbst vieler "professioneller 
Software-Entwickler" (und ihrer Manager) läßt natürlich nicht zu, daß 
Stackprüfungen im produktiven Einsatz der Software noch aktiv sind.
- Nächstes Problem: Was soll der Processor denn noch machen, wenn der 
Stack "knallt"? Und gar noch im produktiven Einsatz? Derartige Probleme 
sollten bereits in der Architektur eines Systems durchdacht und gelöst 
sein. Stattdessen - meine Erfahrung in großen Projekten - 
orientierungsloses Nicht-Design.

Das war die reale Welt der (Software-)Großindustrie schwarz in schwarz 
dargestellt. Bitte keine Kommentare - es kann nur noch besser werden.

Bernhard

von Εrnst B. (ernst)


Lesenswert?

> - Der "Performancefetischismus" selbst vieler "professioneller
> Software-Entwickler" (und ihrer Manager) läßt natürlich nicht zu, daß
> Stackprüfungen im produktiven Einsatz der Software noch aktiv sind.

Was würdest du von einem Auto halten, bei dem man ein ABS einbaut, den 
Firmeneigenen Testfahrer ein paar Runden drehen lässt, und dann das ABS 
wieder ausbaut bevor das Auto an den Endverbraucher geht? Mit der 
Begründung "wurde beim Testen ja auch nie gebraucht"...

Frei nach meinem ehemaligen SoftEng-Prof zum Thema assert und #define 
NDEBUG ...

von Bernhard R. (barnyhh)


Lesenswert?

Die Eiffel-Leute bringen das Beispiel vom Schwimmer, der beim Training 
im Pool das Begleitboot dabei hat, bei der Ärmelkanal-Überquerung aber 
nicht.
Aber ich wollte ja nichts  weiter sagen.

Bernhard

von Falk B. (falk)


Lesenswert?

@ Bernhard R. (barnyhh)

>Die Eiffel-Leute bringen das Beispiel vom Schwimmer, der beim Training
>im Pool das Begleitboot dabei hat, bei der Ärmelkanal-Überquerung aber
>nicht.

Also sterben wie wahre Helden!

MFG
Falk

von Rolf Magnus (Gast)


Lesenswert?

Sind ja ganz tolle Vergleiche.
Nur mal so am Rande: Was soll das Programm bitte sinnvolles machen, wenn 
es feststellt, daß der Stack übergelaufen ist? Das ist so ähnlich wie 
die Checks des Rücgabewerts von malloc auf dem PC. Ist zwar nett, wenn 
man das überall einbaut, aber beim typischen PC-Programm ist der Rechner 
schon lange vorher so mit Auslagerung beschäftigt, daß der Benutzer 
inzwischen den Reset-Knopf gedrückt hat. Ein typisches GUI-Programm hat 
außerdem nicht mal die Chance, dem Benutzer noch ein Fenster anzuzeigen, 
ohne dabei Speicher allokieren zu müssen.
Bei embedded-Software ist das natürlich etwas anders. Aber auch da kann 
ich mir beim Stack-Überlauf nur noch vorstellen, daß das Programm dann 
einen sauberen Reset durchführen kann, aber das war's dann auch schon.

von Michael Wilhelm (Gast)


Lesenswert?

>...Aber auch da kann ich mir beim Stack-Überlauf nur noch vorstellen, daß >das 
Programm dann einen sauberen Reset durchführen kann, aber das war's >dann auch 
schon.

.. und kommt irgendwann wieder an den Punkt.

MW

von X. H. (shadow0815)


Lesenswert?

Das Ding könnte dann aber ein Crash-Log schreiben. Und man steht bei der 
Fehlersuche nicht ganz im dunkeln?!

Wenn es keine 100% fehlerfreie Software gibt, dann sollte das Debugging 
eben nie aufhörren...

Ist anwendungsabhängig.
Windows mit Debugcode laufen zu lassen währe ja keine Freude... 
(speed...)

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

X. H. wrote:

> Das Ding könnte dann aber ein Crash-Log schreiben.

In den EEPROM?

Ich stelle mir gerade vor, wie aus deinem rechten Rückspiegel ein
Crash-Log rausgewackelt kommt, weil der Microcontroller da drin
einen unerwarteten Fehler hatte... ;-)

von X. H. (shadow0815)


Lesenswert?

Ja, in einen Speicher meine ich. Denn der Log ist für eine Person, die 
den Fehler beheben soll.

Bei diesem Stellwerk hätte man vielleicht dadurch den Fehler schneller 
gefunden.

von Karl H. (kbuchegg)


Lesenswert?

Junge.
Wenn dir der Stack überläuft, dann kannst du im Regelfall
gar nichts mehr machen.

1) merkst du den Stacküberlauf in deinem Programm erst wenn
   es bereits zu spät ist. Viel zu spät
2) Abhängig vom Programm, kann ein Stack-Overflow so ziemlich
   alles bewirken. Mit dem gezielten Aufruf eines Crash-Log
   aus dem man auch noch irgendwas ermitteln kann, ist es dann
   normalerwiese nichts mehr.

Auf einem Desktopsystem kann man davon ausgehen, dass das
Betriebssystem noch Speicher vorrätig hat, um weiter arbeiten
zu können.
Auf einem µC ist das aber nicht. Wenn der Stack in die Variablen
reinläuft, bzw. umgekehrt man sich mit Variablenzugriffen den
Stack zerschiest, dann musst du schon froh sein, wenn dein µC
nicht einfach Amok läuft und noch halbwegs geordnet weitermacht.

von Michael Wilhelm (Gast)


Lesenswert?

>nicht einfach Amok läuft und noch halbwegs geordnet weitermacht.

Deshalb werden bei mir alle Controller verlötet! :-)

MW

von Bobby (Gast)


Lesenswert?

Wer ordentlich programmiert, der bekommt auch
keine Stackprobleme.
Es geht ja nicht so sehr um Endlosrekursionen, sondern
eher um die lokalen Arrays, deren Grenzen nicht beachtet
werden.

von yalu (Gast)


Lesenswert?

Leute, programmiert eure Mikrocontroller in Fortran!

Bis Fortran-77 gab's weder Rekursion noch dynamische Speicherverwal-
tung noch sonst irgendetwas, was den Speicherverbrauch zur Laufzeit
zum Lotteriespiel werden lässt. Durch die fehlende Rekursion konnte
alles, aber auch wirklich alles in statisch reservierten Speicher
gelegt werden, selbst die Rücksprungadressen von Unterprogrammauf-
rufen.

Ein Stack ist damit nicht erforderlich, und der Speicherverbrauch
steht schon zur Compilezeit exakt fest. Wenn der Speicher zu knapp
ist, wird das spätestens beim Programmstart erkannt.

Fazit: Zuverlässige Mikrocontrollerprogramme sind nur in Fortran
möglich!

Nun mal Scherz beiseite: Wäre es möglich, das F77-Frontend des GCC mit
dem AVR-Backend zu kombinieren? Vielleicht müsste man eine an den AVR
angepasste Laufzeitbibliothek schreiben. Aber dann sollte es doch
möglich sein, auch Fortran auf dem AVR zu machen, oder?

von Andreas K. (a-k)


Lesenswert?

yalu wrote:

> Fazit: Zuverlässige Mikrocontrollerprogramme sind nur in Fortran
> möglich!

Schon mal was von Occam gehört? Diese Sprache war eigens für Embedded
System konzipiert worden und hatte auch die Eigenheit, den gesamten
Speicherverbrauch statisch rechnen zu können.

Nur hatten die Transputer, für die INMOS das gemacht hat, keine
Interrupts im üblichen Sinn, sondern Prozesse, die von Ereignissen
getriggert wurden (Prozessverwaltung war in Hardware). Damit war INMOS
fein raus, der Speicherverbrauch deterministisch, verschachtelte 
priorisierte Interrupts allerdings schwierig, denn es gab insgesamt nur 
2 Prozessprioritäten.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

yalu wrote:

> Ein Stack ist damit nicht erforderlich, und der Speicherverbrauch
> steht schon zur Compilezeit exakt fest. Wenn der Speicher zu knapp
> ist, wird das spätestens beim Programmstart erkannt.

Genau, und du kaufst einen doppelt so großen Controller, weil du
für alles 5000 Elemente reservieren musst, obwohl du im Normalfall
nur 50 brauchst. ;-)

Im Ernst: wer statisch bekannte Probleme dynamisch löst, dem ist
nicht zu helfen.  Es gibt aber auch Probleme, bei denen die Daten
nicht in vorhersagbarer Menge anfallen und bei denen es darauf
ankommt, im Rahmen der möglichen Ressourcen einfach das Maximum
herauszuholen.

> Nun mal Scherz beiseite: Wäre es möglich, das F77-Frontend des GCC mit
> dem AVR-Backend zu kombinieren?

Es scheitert zumindest erstmal daran, dass FORTRAN zwingend einen
64-bit-FP-Support braucht, damit man die libf77 compilieren kann.

von Εrnst B. (ernst)


Lesenswert?

@yalu:

> Nun mal Scherz beiseite: Wäre es möglich, das F77-Frontend des GCC mit
> dem AVR-Backend zu kombinieren? Vielleicht müsste man eine an den AVR
> angepasste Laufzeitbibliothek schreiben. Aber dann sollte es doch
> möglich sein, auch Fortran auf dem AVR zu machen, oder?

Die sind schon "verheiratet", aber wg. den fehlenden Bibliotheken wird 
der AVR-F77 wohl bei den üblichen Binärdistributionen nicht 
mitgeliefert.

=> selber die GCC-Quelltexte übersetzen, da kannst du das 
Fortran-Frontend einfach einschalten.

Bei mir hat sich z.B. der avr-gcj (Java-Compiler) mitinstalliert, 
mangels libgcj für den AVR jedoch nicht verwendbar. Freiwillige?

von yalu (Gast)


Lesenswert?

Andreas Kaiser schrieb:
> Schon mal was von Occam gehört?

Natürlich, ich habe sogar mal etwas damit programmiert. Allerdings
gerade einmal so viel, um nachzuweisen, dass eine Transputer-
Schaltung, die ich damals entwickelt habe, funktioniert. Ein wenig
mehr habe ich in Assembler gemacht. Irgenwie fand ich den Aufbau der
Transputer-Befehle sehr pfiffig.

Jörg Wunsch schrieb:
> Es scheitert zumindest erstmal daran, dass FORTRAN zwingend einen
> 64-bit-FP-Support braucht, damit man die libf77 compilieren kann.

Naja, wenn man Fortran ernsthaft auf µC benutzen wollte (ich
persönlich will zwar, nur der Ernst dazu fehlt noch etwas ;-)), würde
man wahrscheinlich sowieso die libF77 durch etwas handlicheres,
vergleichbar mit der AVR-Libc, ersetzen.

Ernst Bachmann schrieb:
> Die sind schon "verheiratet", aber wg. den fehlenden Bibliotheken
> wird der AVR-F77 wohl bei den üblichen Binärdistributionen nicht
> mitgeliefert.

Darauf wird es wohl hinauslaufen, dass man bibliotheksmäßig etwas
Neues stricken muss. Mal schauen, wenn ich irgendwann demnächst einen
Mußetag habe (was leider nicht wahrscheinlich ist), könnte ich mal
versuchen, eine minimalistsiche Laufzeitbibliothek anzufangen, nur so
als Proof-of-Concept ;-)

von Andreas K. (a-k)


Lesenswert?

yalu wrote:

> Irgenwie fand ich den Aufbau der Transputer-Befehle sehr pfiffig.

Aber nur wenn man damit Occam realisieren wollte, denn dafür und nur 
dafür war der Befehlssatz vorgesehen. In C sah das weniger schön aus, 
Ausdrücke wie (++i != 10) oder ?: wurden etwas umständlich.

Und das hier skizzierte Stack-Problem war grad da in C besonders 
perfide. Weil man die Stacks aller zig Prozesse schon gern im schnellen 
internen RAM haben wollte, aber das genau war bei 2KB kaum möglich ohne 
jeden Prozess bytegenau auszurechnen.

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Dummerweise ist eben die Trennung zwischen reinen Sprachelementen
und Bibliothek bei FORTRAN nicht so strikt wie bei C.  Dadurch
brauchst du letztlich eine Bibliothek, um den Compiler überhaupt
benutzen zu können.

Allerdings habe ich mittlerweile Schwierigkeiten, ein "Hello, world!"
in FORTRAN zu zimmern, insofern ist mein Interesse an einem derartigen
Compiler eher marginal.  Interessanter fände ich (neben Ada, was ja
offenbar bereits ganz gut in die Gänge gekommen ist) dann eher noch
Pascal.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.