GCC Compiler: Optimierung ein oder aus?

OP #795071
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
Gast #795208
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?

??
Gast #795451
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".
Gast #795981
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.
#796575
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
#796581
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
Gast #796756
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.
#796916
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
#796929
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 ...
Gast #797371
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.
Gast #797377
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
#797392
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...)
#797575
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.
Gast #797641
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?
#797660
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.
Moderator Persönliche Seite #797681
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.
#797685
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?
Gast #797753
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 ;-)
#797810
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.
Moderator Persönliche Seite #797816
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren