Forum: Mikrocontroller und Digitale Elektronik AVR-GCC: Optimierung?


von Hermann G. (df2ds)


Lesenswert?

Hallo zusammen,
ich schreibe gerade an einem kleinen Ladecontroller und bin dabei auf 
eine Frage gestoßen, die ich gern im Vorfeld klären möchte (also bevor 
ich den Code laufen lasse). Es geht um folgenden Codeausschnitt:
1
while (   (_batteryVoltageCB() <= _vTerminateCharge)
2
       && (_batteryCurrentCB() < _iChargeMax)
3
       && (_pwmValue < 255)
4
      ) _setChargerPWM(++(_pwmValue));
Beabsichtigt ist, dass die Funktionen ...CB() bei jedem 
Schleifendurchlauf ausgeführt werden! Geht das so, oder muss ich da 
"vorsorglich" eingreifen, damit der Compiler nicht "denkt", dass ein 
Aufruf für die ganze while(){}-Anweisung genügt?

Danke im Voraus für konstruktive Hinweise!
  Hermann

von Einer K. (Gast)


Lesenswert?

Hermann G. schrieb:
> oder muss ich da "vorsorglich" eingreifen,
Aber ganz sicher!

Bitte einmal das C oder C++ Buch deiner Wahl lesen!

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


Lesenswert?

Hermann G. schrieb:
> Beabsichtigt ist, dass die Funktionen ...CB() bei jedem
> Schleifendurchlauf ausgeführt werden! Geht das so, oder muss ich da
> "vorsorglich" eingreifen, damit der Compiler nicht "denkt", dass ein
> Aufruf für die ganze while(){}-Anweisung genügt?

Der erste Satz ist etwas mehrdeutig.

Prinzipiell werden Funktionen erstmal für jeden Schleifendurchlauf 
aufgerufen.

Aber: es greift natürlich das "Kurzschluss-Prinzip" für logische 
Verknüpfungen. Wenn also das Ergebnis von_batteryVoltageCB() größer ist 
als _vTerminateCharge, dann wird _batteryCurrentCB() nicht mehr 
aufgerufen, denn das Ergebnis des gesamten booleschen Ausdrucks ist an 
dieser Stelle klar.

Bekommst du irgendwie extra Geld für jeden Unterstrich? ;-) Oder warum 
sonst muss bei dir alles mit so einem Zeichen beginnen? Denk dran, 
Unterstrich gefolgt von Kleinbuchstabe ist OK, gefolgt von einem zweiten 
Unterstrich oder einem Großbuchstaben gehört der Bezeichner aber zum 
"implementation namespace", also Compiler und (Standard-)Bibliothek.

von Ingo Less (Gast)


Lesenswert?

Das kommt darauf an, wie deine Variablen aufgebaut sind. Volatile -> 
geht. Nicht volatile -> sollte schief gehen wenn der Optimizer zu bissig 
is.

von Georg G. (df2au)


Lesenswert?

Den GCC kenne ich nicht bis ins Detail. Aber es gibt C-Compiler, die von 
rechts nach links und solche, die von links nach rechts den Ausdruck 
abarbeiten. Und dann gibt es solche, die die Abarbeitung abbrechen, 
sobald das Ergebnis (in deinem Fall "falsch") feststeht.

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


Lesenswert?

Georg G. schrieb:
> Und dann gibt es solche, die die Abarbeitung abbrechen, sobald das
> Ergebnis (in deinem Fall "falsch") feststeht.

Nur diese sind standardkonform.

von Einer K. (Gast)


Lesenswert?

Es gilt die "Short ircuit evaluation", solange das dem Kompiler nicht 
explizit verboten wird.
https://de.wikipedia.org/wiki/Kurzschlussauswertung

Da beißt auch ein volatile keinen Faden von ab.

von Georg G. (df2au)


Lesenswert?

Als Nachtrag: Ich bewundere Programmierer, die keine Klammer zu viel 
setzen, n+1 Funktionen in einer Zeile unterbringen können. Aber ich habe 
mit dieses Spezies nie gern zusammen gearbeitet. Ich bevorzuge defensive 
Programmierung. Der Code wird nicht langsamer, nur, weil übersichtlich 
geschrieben wurde und auch mal komplexe Ausdrücke zerlegt wurden und 
eine unnötige Klammer gesetzt wurde. Spätestens, wenn in zwei Jahren der 
Nachfolger eine Änderung machen muss, freut er sich über diesen Stil.

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


Lesenswert?

Arduino Fanboy D. schrieb:
> Alles Blödsinn!

Vor allem alle Pauschalisierungen …

Es stehen hier so viele verschiedene Dinge in den Antworten, dass es 
natürlich schon recht „interessant“ anmutet, sie alle in Bausch und 
Bogen als „Blödsinn“ abzutun.

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


Lesenswert?

Georg G. schrieb:
> Ich bevorzuge defensive Programmierung.

Die würde in diesem Falle (falls der Boolesche Ausdruck tatsächlich 
exakt so beabsichtigt ist) allerdings darin münden, dass man eine 
zusätzliche Funktion einführen muss, die die Teilbedingungen dieses 
Ausdrucks sequenziell abarbeitet. Nur so kann man ihren Rückkehrwert 
auch als Abbruchbedingung für die Schleife benutzen.

von Einer K. (Gast)


Lesenswert?

Jörg W. schrieb:
> Arduino Fanboy D. schrieb:
>> Alles Blödsinn!
>
> Vor allem alle Pauschalisierungen …
>
> Es stehen hier so viele verschiedene Dinge in den Antworten, dass es
> natürlich schon recht „interessant“ anmutet, sie alle in Bausch und
> Bogen als „Blödsinn“ abzutun.

Ja...
Habs ja schon weg gemacht.....

Zum thema:
Hier würde sich evtl eine do{}while() anbieten.

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


Lesenswert?

Arduino Fanboy D. schrieb:

> Habs ja schon weg gemacht.....

Gut, hat sich mit meinem Beitrag dann überschnitten.

> Zum thema:
> Hier würde sich evtl eine do{}while() anbieten.

Falls es nicht wichtig ist, ob die Schleife ggf. (bei initial bereits 
unwahrem Steuerausdruck) gar nicht durchlaufen werden soll, könnte das 
eine Variante sein. Da kann man auch gleich eine Endlosschleife nehmen 
und mit expliziten breaks verlassen.

von Rolf M. (rmagnus)


Lesenswert?

Ingo Less schrieb:
> Das kommt darauf an, wie deine Variablen aufgebaut sind. Volatile ->
> geht. Nicht volatile -> sollte schief gehen wenn der Optimizer zu bissig
> is.

Es geht um Funktionen, nicht um Variablen.

Georg G. schrieb:
> Der Code wird nicht langsamer, nur, weil übersichtlich
> geschrieben wurde und auch mal komplexe Ausdrücke zerlegt wurden und
> eine unnötige Klammer gesetzt wurde. Spätestens, wenn in zwei Jahren der
> Nachfolger eine Änderung machen muss, freut er sich über diesen Stil.

Ich finde den Code so eigentlich recht übersichtlich, und er enthält 
schon jede Menge der von dir gewünschten unnötigen Klammern. Allerdings 
würde ich den Inhalt der Schleife etwas klarer von der Bedingung 
trennen.
Wie würdest du es denn schreiben, damit es übersichtlicher ist?

von Hermann G. (df2ds)


Lesenswert?

Boh, so viele Antworten in so kurzer Zeit... Danke!

Erst einmal die einfachen Dinge:
* Die Unterstriche habe ich deshalb, weil der ganze Codeschnipsel nur 
lokale Variable innerhalb (m)einer Library benutzt.
* Über Schreibweise und Formatierung von Code lässt sich herrlich 
streiten - das soll aber hier nicht das Thema sein.

Offensichtlich habe ich meine Frage nicht ganz eindeutig formuliert, wie 
Jörg schon richtig bemerkt hat. Daher hier noch einmal zur 
Verdeutlichung:

Mir ist völlig klar, dass die Schleife abgebrochen wird, wenn eine der 
Bedingungen nicht erfüllt ist, darüber müssen wir nicht diskutieren. 
Aber wenn ALLE Bedingungen erfüllt sind, wird
1
setChargerPWM(++(_pwmValue))
 ausgeführt und anschließend wieder zum Schleifenkopf verzweigt. Jetzt 
frage ich mich, ob bei dem nächsten Schleifendurchlauf die 
*CB()-Funktion(en) wieder ausgeführt werden oder ob (evtl. noch in 
Registern des Prozessors vorhandene) "alte" Werte *aus dem vorherigen 
Schleifendurchlauf* benutzt werden. Das wäre für die Applikation nämlich 
"tödlich".

Ich hoffe, die Fragestllung ist jetzt eindeutig.

von Rolf M. (rmagnus)


Lesenswert?

Hermann G. schrieb:
> Aber wenn ALLE Bedingungen erfüllt sind, wird setChargerPWM(++(_pwmValue))
> ausgeführt und anschließend wieder zum Schleifenkopf verzweigt. Jetzt
> frage ich mich, ob bei dem nächsten Schleifendurchlauf die
> *CB()-Funktion(en) wieder ausgeführt werden oder ob (evtl. noch in
> Registern des Prozessors vorhandene) "alte" Werte *aus dem vorherigen
> Schleifendurchlauf* benutzt werden.

Natürlich wird die Funktion wieder aufgerufen, es sei denn, der Compiler 
kann garantieren, dass sich durch das Weglassen des Aufrufs nichts 
ändert.

von foobar (Gast)


Lesenswert?

> * Die Unterstriche habe ich deshalb, weil der ganze Codeschnipsel nur
> lokale Variable innerhalb (m)einer Library benutzt.

Dann mach die Variablen einfach "static".  Ein Underscore hilft nur 
anscheinend - sobald ein anderes Library den gleichen Namen nutzt, 
geht's schief.  Wenn überhaupt, dann musst du einen Library-spezifischen 
Prefix verwenden, z.B. BatLib_xxx - macht aber nur Sinn, wenn das 
Library aus mehreren C-Files besteht, die auf diese gemeinsamen Namen 
zugreifen sollen.

von Hermann G. (df2ds)


Lesenswert?

Super, dann muss ich mir an dieser Stelle keine weiteren Gedanken 
machen.

Danke nochmal für alle eure Antworten!
  Hermann

von Falk B. (falk)


Lesenswert?

Hermann G. schrieb:
> Hallo zusammen,
> ich schreibe gerade an einem kleinen Ladecontroller und bin dabei auf
> eine Frage gestoßen, die ich gern im Vorfeld klären möchte (also bevor
> ich den Code laufen lasse). Es geht um folgenden Codeausschnitt:while (
> (_batteryVoltageCB() <= _vTerminateCharge)
>        && (_batteryCurrentCB() < _iChargeMax)
>        && (_pwmValue < 255)
>       ) _setChargerPWM(++(_pwmValue));

> Beabsichtigt ist, dass die Funktionen ...CB() bei jedem
> Schleifendurchlauf ausgeführt werden!

Dann sollte man das auch explizit und leicht lesbar so hinschreiben. Die 
meisten Tricks mit der ultrakompakten Schreibweise, wie sie C zuläßt, 
gehen meist daneben.

Strukturierte Programmierung auf Mikrocontrollern

http://c2.com/cgi/wiki?ThreeStarProgrammer

> Geht das so, oder muss ich da

Nö, wurde ja schon erklärt.

> "vorsorglich" eingreifen, damit der Compiler nicht "denkt", dass ein
> Aufruf für die ganze while(){}-Anweisung genügt?

von leo (Gast)


Lesenswert?

Georg G. schrieb:
> Den GCC kenne ich nicht bis ins Detail.

Warum glaubst du dann hier schreiben zu muessen. Das ist alles 
Stumpfsinn.

Stichwort: "Short-circuit evaluation".

I.e. nix rechts nach links oder vielleicht.
Re TO: die *CB Funktionen werden immer aber nur wenn noetig fuer das 
Gesamtergebnis aufgerufen.

leo

von leo (Gast)


Lesenswert?

Ingo Less schrieb:
> Das kommt darauf an, wie deine Variablen aufgebaut sind. Volatile ->
> geht.

Das hat absolut nichts mit volatile zu tun. Die Abfragen erfolgen 
schlicht so weit, bis ein fixes Ergebnis vorliegt.

leo

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


Lesenswert?

Lieber leo, irgendwie kommst du hier 3 h zu spät. Das war doch alles 
schon geklärt.

von leo (Gast)


Lesenswert?

Jörg W. schrieb:
> Lieber leo, irgendwie kommst du hier 3 h zu spät. Das war doch
> alles
> schon geklärt.

Ja, verteilt. Aber so absolut falsche Aussagen kann ich tw. einfach 
nicht immer unwidersprochen lassen.

BTW "nicht standardkonform" kann man auch als "fehlerhaft", "falsch" 
usw. bezeichnen. Wenn die Code-Ausfuehrung nicht mehr stimmt, ist das 
durchaus was anderes, als die Festlegung von e.g. "seconds since xxx", 
die MS sehr oft gewechselt hat.

leo

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.