Forum: Mikrocontroller und Digitale Elektronik Funktionsaufruf bei Optimization -O1


von Maddin (Gast)


Lesenswert?

Ich kompiliere mit dem AVR-gcc und der Optimization -O1. Innerhalb einer 
Funktion verwende ich
1
if ( zahl )
2
{
3
//fuehre aus
4
}
.

Dabei ist zahl 0 oder eine andere Zahl. Zahl ist außerdem per
1
#define zahl 0
 definiert. Die Funktion soll also nur dann etwas bewirken wenn zahl!=0. 
Ich könnte beim Aufruf auch schreiben
1
if (zahl) function();
,was augenscheinlich besser zu sein scheint, denn damit wird definitiv 
verhindert, dass die Funktion überhaupt aufgerufen wird. 
(Zeitersparnis?)

Wird im Fall der genannten Optimization das eventuelle Laufzeitdefizit 
im ersteren Fall erkannt und die Funktion NICHT aufgerufen wenn zahl 
"null" ist? Oder ist dafür eine höherwertige Optimization erforderlich?

von Floh (Gast)


Lesenswert?

Wenn zahl durch eine 0 ersetzt wird (im Präprozessor), ist die Abfrage 
if(zahl) witzlos, da das sofort durch den Compiler wegoptimiert wird.

von Maddin (Gast)


Lesenswert?

Floh schrieb:
> Wenn zahl durch eine 0 ersetzt wird (im Präprozessor), ist die Abfrage
> if(zahl) witzlos, da das sofort durch den Compiler wegoptimiert wird.

Ersteinmal ist hier nix witzlos. Ich glaube das Problem wurde noch nicht 
erkannt.
Die Abfrage macht schon Sinn, wenn der Aufruf der Funktion im Programm 
nicht überall von Hand gelöscht werden soll, nur weil eine 
kundenspezifische Firmware erstellt wird.

Ich wollte eher wissen ob auch der Funktionsaufruf! durch den Compiler 
wegoptimiert wird, wenn IN der Funktion if(zahl) steht und somit die 
Funktion wirkungslos wird. (Ob Ja oder Nein in beiden Fällen wird die 
Funktion wirkungslos... aber wird sie aufgerufen??)

Gruß Maddin

von (prx) A. K. (prx)


Lesenswert?

Wenn Inlining nicht vollständig ausgeschlossen ist und dem Compiler der 
Inhalt der Funktion bekannt ist, dann kann der Compiler eine leere 
Funktion als überflüssig erkennen und den Aufruf wegoptimieren.

von Karl H. (kbuchegg)


Lesenswert?

Maddin schrieb:
> Floh schrieb:
>> Wenn zahl durch eine 0 ersetzt wird (im Präprozessor), ist die Abfrage
>> if(zahl) witzlos, da das sofort durch den Compiler wegoptimiert wird.
>
> Ersteinmal ist hier nix witzlos. Ich glaube das Problem wurde noch nicht
> erkannt.

Ich glaube das Problem wurde nicht richtig beschrieben.
Was du willst ist, mit Präprozessor Hilfe, Teile deines Programmes gar 
nicht erst mitkompilieren zu lassen

#if zahl == 0
   function();
#endif

von (prx) A. K. (prx)


Lesenswert?

Oder sowas wie
1
#if zahl == 0
2
  #define function(x)
3
#else
4
  extern void function(int);
5
#endif

von Maddin (Gast)


Lesenswert?

A. K. schrieb:
> Wenn Inlining nicht vollständig ausgeschlossen ist und dem Compiler der
> Inhalt der Funktion bekannt ist, dann kann der Compiler eine leere
> Funktion als überflüssig erkennen und den Aufruf wegoptimieren.

Gut Inlining sagt mir nun nichts, aber ein definitives Ja oder Nein ist 
es auch nicht. Aber das reicht mir als Beantwortung.


Karl Heinz Buchegger schrieb:
> Was du willst ist, mit Präprozessor Hilfe, Teile deines Programmes gar
> nicht erst mitkompilieren zu lassen

Schon Richtig.

Karl Heinz Buchegger schrieb:
> #if zahl == 0
>    function();
> #endif

Ob genau dies der Compiler bei der Optimierung vornimmt wollte ich 
wissen. Unabhängig davon hast du mir damit jedoch einen wunderbaren 
Vorschlag gegeben, meinen Code zu optimieren. An soetwas habe ich noch 
garnich gedacht.

Vielen Dank euch

von JensM (Gast)


Lesenswert?

Wenn Programmteile schon bei der Compilierung zu/abgeschaltet werden 
sollen, so macht man das üblicherweise mit Define Schalter (#ifdef/ 
#if..).

Damit wird der Code schon vom Präprozessor entfernt oder eingefügt.
Man ist dann nicht vom Codeoptimierer abhängig.

Es ist dann auch für Entwickler die den Programmcode anschaut 
ersichtlich, dass die Funktion zur Compilierzeit zu/abgeschaltet werden.

Allgemein benötigt ein Funktionsaufruf mehr Zeit als Inline 
(zusätzlicher Aufruf und return).
Was der Codeoptimierer daraus macht ist eine andere Sache.
Natürlich verwendet man trotzdem Funktionen weil es das Programm 
übersichtlicher macht, Programmteile nur 1Mal vorhanden sind... .

Wenn
if(false) funktion();
wird die Funktion natürlich nicht aufgerufen.
Es entscheidet doch das if, ob die Funktion aufgerufen wird oder nicht.
Dabei wird der Funktionsaufruf übersprungen.

Bei
if (false)
{
 // code
}
wir der Programmblock übersprungen.

-> gleicher Zeitbedarf für beide Versionen.
Natürlich ohne Betrachtung von Codeoptimierungen.

Gruss JensM

von Maddin (Gast)


Lesenswert?

JensM schrieb:
> if(false) funktion();
> wird die Funktion natürlich nicht aufgerufen.
> Es entscheidet doch das if, ob die Funktion aufgerufen wird oder nicht.
> Dabei wird der Funktionsaufruf übersprungen.


Ja natürlich.
> Bei
> if (false)
> {
>  // code
> }
> wir der Programmblock übersprungen.

Richtig, aber dabei wurde bereits in die Funktion gesprungen, dann erst 
wird geprüft und festgestellt, dass der Code nicht ausgeführt werden 
soll.

> -> gleicher Zeitbedarf für beide Versionen.

Wirklich? Auch nach dem bereits in die Funktion gesprungen wurde?

von (prx) A. K. (prx)


Lesenswert?

Maddin schrieb:

> Gut Inlining sagt mir nun nichts, aber ein definitives Ja oder Nein ist
> es auch nicht.

Kann es auch nicht sein, weil dieses Verhalten von der Sprache her nicht 
definiert ist und völlig vom Compiler und dessen Launen abhängt.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

JensM schrieb:
> Wenn
> if(false) funktion();
> wird die Funktion natürlich nicht aufgerufen.
> Es entscheidet doch das if, ob die Funktion aufgerufen wird oder nicht.
> Dabei wird der Funktionsaufruf übersprungen.

Nein, hier nicht (zumindest GCC). Es wird nicht nur die Funktion nicht 
aufgerufen, sondern erst überhaupt kein Funktionsaufruf erzeugt. 
Ebenso wird keine if-Abfrage erzeugt.

Bitte ein Beispielcode übersetzen und nachkontrollieren!

> Bei
> if (false)
> {
>  // code
> }
> wir der Programmblock übersprungen.

Nein, er wird komplett in die Tonne gekloppt.

> -> gleicher Zeitbedarf für beide Versionen.

Wieder korrekt, weil für beide Varianten der Codeverbrauch = 0 ist

von Maddin (Gast)


Lesenswert?

Wie ich bereits in der ersten Zeile schrieb befindet sich


if (false)
{
 // code
}

in der aufzurufenden Funktion.

von Jasch (Gast)


Lesenswert?

Maddin schrieb:
> Ich kompiliere mit dem AVR-gcc und der Optimization -O1. Innerhalb einer
> Funktion verwende ich
>
1
> if ( zahl )
2
> {
3
> //fuehre aus
4
> }
5
>
.
>
> Dabei ist zahl 0 oder eine andere Zahl. Zahl ist außerdem per
>
1
> #define zahl 0
2
>
 definiert. Die Funktion soll also nur dann etwas bewirken wenn
> zahl!=0. Ich könnte beim Aufruf auch schreiben
>
1
> if (zahl) function();
2
>
> ,was augenscheinlich besser zu sein scheint, denn damit wird definitiv
> verhindert, dass die Funktion überhaupt aufgerufen wird.
> (Zeitersparnis?)

Ja.

Besser wäre wie in anderen Antworten vorgeschlagen gleich den 
Präprozessor dafür zu nehmen wie Gott es vorgesehen hat.

> Wird im Fall der genannten Optimization das eventuelle Laufzeitdefizit
> im ersteren Fall erkannt und die Funktion NICHT aufgerufen wenn zahl
> "null" ist? Oder ist dafür eine höherwertige Optimization erforderlich?

Das geht mit so ziemlich keiner Optimierung, der Compiler kann 
realistischerweise weder die Funktion "verschwinden" lassen noch den 
Aufruf weglassen - jedenfalls wenn Aufruf und Funktion in verschiedenen 
Files sind.

Die Gründe sind simpel:

- man kann von einer Funktion die Adresse nehmen, gibt es mehr als ein 
File kann der Compiler nicht wissen ob das irgendwo getan wird, deshalb 
kann er die Funktion nicht komplett weglassen - sogar wenn sie leer ist,

- beim compilieren von File A weiss der Compiler nicht wie in File B, C, 
... definierte Funktionen überhaupt aussehen, deshalb kann er den Aufruf 
nicht einfach weglassen.

Ein Compiler der über alle Files optimiert könnte sowas rausfinden, mit 
recht unschönen Folgen für Laufzeit und Speicherverbrauch.

von ikorb (Gast)


Lesenswert?

Jasch schrieb:
> Das geht mit so ziemlich keiner Optimierung, der Compiler kann
> realistischerweise weder die Funktion "verschwinden" lassen noch den
> Aufruf weglassen - jedenfalls wenn Aufruf und Funktion in verschiedenen
> Files sind.

Dann lässt man das halt den Linker machen - mit den GNU-Tools geht das 
via "-ffunction-sections" beim Compilieren und "-Wl,--gc-sections" beim 
Linken.

> Ein Compiler der über alle Files optimiert könnte sowas rausfinden, mit
> recht unschönen Folgen für Laufzeit und Speicherverbrauch.

"-fwhole-program" beim gcc, mit einigen Einschränkungen

von ... (Gast)


Lesenswert?

wird eigentlich sonst noch jemand übel, wenn man hört dass jemand wie 
"Maddin" KUNDENspezifische Software schreibt? Welcher Kunde hat denn 
sowas verdient?

Vorkentnisse == 0 && Einarbeitungfähigkeiten == 0

Die Grundlegende Frage wird von jedem Anfänger-Optimierungs Tutorial 
beantwortet... eigentlich direkt von dem das man bei google zuerst 
findet, würde man die schlagworete der frage bei google mal eingeben.

 P E I N L I C H .

http://lmgtfy. com/?q=gcc+code+optimization+if+statement

3. Link. http://tldp.org/LDP/LG/issue71/joshi.html

Nummer 5.

von Maddin (Gast)


Lesenswert?

... schrieb:
> wird eigentlich sonst noch jemand übel, wenn man hört dass jemand wie
> "Maddin" KUNDENspezifische Software schreibt? Welcher Kunde hat denn
> sowas verdient?
>
> Vorkentnisse == 0 && Einarbeitungfähigkeiten == 0
>
> Die Grundlegende Frage wird von jedem Anfänger-Optimierungs Tutorial
> beantwortet... eigentlich direkt von dem das man bei google zuerst
> findet, würde man die schlagworete der frage bei google mal eingeben.
>
>  P E I N L I C H .
>
> http://lmgtfy. com/?q=gcc+code+optimization+if+statement
>
> 3. Link. http://tldp.org/LDP/LG/issue71/joshi.html
>
> Nummer 5.

Lächerlich bist hier nur du. Was fällt dir überhaupt ein mich auf diese 
bescheuerte Art und Weise zu kritisieren?

Weißt du etwas über meine Arbeit, mein Projekt, meine Kunden oder meinen 
Karrierehintergrund?

Vielleicht bin ich ein 39jähriger hochbezahlter Softwaredesigner der 
gerade die Software der neuen VW-Lenkung programmiert. Dem sollte 
soetwas peinlich sein.

Vielleicht bin ich ein einsamer Kuhbauer der in nächtlicher Stunde im 
Keller rumbastelt und für seine Kunden (Kühe) vollelektronische 
Kuhglocken programmiert. Sollte dem etwa die Frage peinlich sein?

Vielleicht bin ich ein junger Student der bereits jetzt in industriele 
Projekte eingebunden ist. Neben dem Studium und in den Ferien 
Erfahrungen sammelt die er später gebrauchen wird und Geld verdient und 
die deutsche Kaufkraft deutlich steigert und dabei in der kleinen Firma 
ein Knowhow-Träger ist (ich weiß das kann relativ sein).

Alles egal solange es um Auslieferung von Software an bezahlende Kunden 
geht? Denke ich nicht!!

Die Software läuft sein Monaten, ist strukturiert und die zugehörige 
Hardware zuverlässig! Und alles durch meinen eigenen Geist und 
Tatendrang geschaffen! Ob dus glaubst oder nicht. Darauf bin ich 
verdammt stolz. In ganz Deutschland, selbst in teilen Europa läuft meine 
Software auf meiner Hardware. Diesen Erfolg kannst du mir mit deiner 
PÖBELEI nicht nehmen!

Und noch einmal. Meine Frage ware einzieg und allein:
"Optimiert der Compiler eine komplette Funktion ja sogar deren Aufruf 
weg, wenn deren INHALT augenscheinlich keine Bedeutung hat."

Ob dies durch google rauszufinden war? Ich weiß es nicht. Ich habe nicht 
danach gesucht, weil ich annahm die Antwort sei nicht leicht zu finden. 
(Und in Anbetracht meines (noch geringen) Stundenlohns zog ich dieses 
Forum zu Rate.) Nun siehst du an Beiträgen wie von "A.K." und "Jasch" 
das dies sogar zutrifft. Auf den Zusammenhang mit den unterschiedlichen 
Files wäre ich auch nicht so gekommen.

Allen anderen danke ich für die sachliche Erklärung auch wenn das 
angefallende Nebenprodukt mit dem
1
#define irgendwas
die Fragestellung beseitigt und den Code um einiges sauberer und zu dem 
macht was es werden sollte.

So jetz bin ich froh dass das raus is. Du hast mich heute morgen echt 
sauer gemacht. Aber wahrscheinlich hast du dein Ziel damit erreicht.

Gruß

Maddin

von Jasch (Gast)


Lesenswert?

ikorb schrieb:
> Jasch schrieb:
>> Das geht mit so ziemlich keiner Optimierung, der Compiler kann
>> realistischerweise weder die Funktion "verschwinden" lassen noch den
>> Aufruf weglassen - jedenfalls wenn Aufruf und Funktion in verschiedenen
>> Files sind.
>
> Dann lässt man das halt den Linker machen - mit den GNU-Tools geht das
> via "-ffunction-sections" beim Compilieren und "-Wl,--gc-sections" beim
> Linken.

Hmm, hmm. Kann der AVR-GCC das auch schon?

>> Ein Compiler der über alle Files optimiert könnte sowas rausfinden, mit
>> recht unschönen Folgen für Laufzeit und Speicherverbrauch.
>
> "-fwhole-program" beim gcc, mit einigen Einschränkungen

Das dürfte eines der weniger getesteten Features sein, schliesslich ist 
sowas bei grosser Software auf grossen Plattformen - ich denke da so an 
Linux-Kernel, glibc, OpenOffice, grössere Embedded-Sachen, Sachen mit 
5-, 6-, 7-stelliger Anzahl Codezeilen halt - wohl kaum praktikabel. Hah, 
"Assume that the current compilation unit represents the whole program", 
wie praktisch brauchbar ist das denn?

Überhaupt, es gibt ja Lösungen für das Problem die sogar laut Standard 
funktionieren müssen - sich auf die nicht garantierten Eigenschaften 
des Optimizers eines ganz bestimmten Compilers zu verlassen ist eher 
mutig bis gegebenenfalls nervenzerfetzend.

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.