Arduino Uno:
Überlicherweise intitialisiert man den Wert einer unveränderlichen
Variable gleich in der Delaration:
1
intvariable=15;
Ich möchte die Variable aus Gründen der Übersicht dort im Programmtext
setzen, wo sie auch eingesetzt wird. Dies auch deswegen, weil für
jedesmal, wo eine bestimmte Funktion im Programm benötigt wird ein
Programmblock in den loop Teil kopiert und die Werte der Variablen für
die jeweilige Anforderung spezifiziert werden müssen. Die näheren
Umstände für diese Notwendigeit werde ich in einem anderen Posting
diskutieren. Dazu gehört auch die oben genannte unveränderliche
Variable. Wenn ich diese Variable in der Deklaration initialisiere, wäre
das Kilometer weit weg und von daher unübersichtlich.
Jetzt meine Fragen: Die Zuweisung der nicht variablen Variable
1
variable=15;
würde bei jedem Durchlauf des loop stattfinden, ohne dass sich der Wert
an anderer Stelle verändert.
Frage 1) Ist der Arduino Compiler intelligent genug, das zu erkennen und
die Zuweisung nur einmal vorzunehmen?
Frage 2) Ist er sogar intelligent genug, die Variable im Flash statt im
RAM zu speichern?
Hustle schrieb:> Frage 1) Ist der Arduino Compiler intelligent genug, das zu erkennen und> die Zuweisung nur einmal vorzunehmen?
Der GCC ist bei Optimierung recht gut aufgestellt.
> Frage 2) Ist er sogar intelligent genug, die Variable im Flash statt im> RAM zu speichern?
Er ist intelligent genug, Variablen ganz wegzulassen oder
ausschliesslich in Registern zu halten, wenn der Rest des Programms dem
nicht entgegen steht.
Allerdings ist für wirklich qualifizierte Antworten deine Frage zu vage.
Programmstücke beschreibt man nicht in Prosa, sondern in Code.
Hustle schrieb:> Überlicherweise intitialisiert man den Wert einer unveränderlichen> Variable gleich in der Delaration:> int variable = 15;
Eine unveränderliche Variable, nennt sich Konstante.
Also wäre eher:
> const int bezeichner = 15;
eine angemessene Ausformulierung
Das Const kennzeichnet das Element als "read only".
Das verhindert ungewollte Veränderungen, bzw. schreit der Compiler, wenn
er bemerkt, dass du das versuchst.
Auch erlaubt das const setzen, dem Compiler weitergehende Optimierungen.
Soweit wie möglich, wird der Kompiler kein RAM für eine solche Konstante
reservieren, sondern den Wert direkt in den generierten Code
einflechten.
In dem Fall ist es natürlich egal wo die die Definition/Deklaration hin
schreibst.
-------------
Hustle schrieb:> Ich möchte die Variable aus Gründen der Übersicht dort im Programmtext> setzen, wo sie auch eingesetzt wird. Dies auch deswegen, weil für> jedesmal, wo eine bestimmte Funktion im Programm benötigt wird ein> Programmblock in den loop Teil kopiert und die Werte der Variablen für> die jeweilige Anforderung spezifiziert werden müssen. Die näheren> Umstände für diese Notwendigeit werde ich in einem anderen Posting> diskutieren. Dazu gehört auch die oben genannte unveränderliche> Variable. Wenn ich diese Variable in der Deklaration initialisiere, wäre> das Kilometer weit weg und von daher unübersichtlich.
Das verstehe ich nicht.
Möchtest du lokale Konstanten erzeugen?
Auch für diese kann man sagen, dass der Kompiler das möglichst weit
optimiert.
Was da wirklich mit passiert, muss man sich wohl im erzeugten Code
anschauen.
Tipp:
Nicht so sehr um Microoptimierungen kümmern, sondern eher darum, dass
der Code übersichtlich bleibt/wird.
Ist das eine globale Variable, welche innerhalb der Schleife vor einem
Funktionsaufruf gesetzt wird? Dann kann der Compiler das nicht
optimieren, da er nicht weiß ob der Funktionsaufruf die Variable nicht
verändert hat; es sei denn die Funktion und alle davon aufgerufenen
stehen in der selben Datei.
Letztlich kostet so ein Zugriff eh nur ein paar Takte. Klarheit bringt
es, sich den disassemblisierten Code anzusehen.
A. K. schrieb:> Allerdings ist für wirklich qualifizierte Antworten deine Frage zu vage.> Programmstücke beschreibt man nicht in Prosa, sondern in Code.
Okay. Hier ein zur Beurteilung der Optimierung auf das Wesentliche
konstruiertes Programm. Hier würde in jedem Loop Durchlauf die gleiche
Zuweisung stattfinden. Variable und eine Wertzuweisung sind im
Programmtext unentbehrlich, da der Wert später zweimal gebraucht wird.
Das auszugebende Ergebnis lässt sich zur Compilerzeit nicht
vorausberechnen, da ADC erst zur Laufzeit bekannt wird. Sinnvoll
bezüglich der Optimierung wäre die sich nicht wiederholende Zuweisung in
jedem Loop.
1
intvariable,ADC;
2
3
voidsetup(){
4
Serial.begin(9600);
5
}
6
7
voidloop(){
8
variable=15;// Das ist der sich in jedem Loop wiederholende Befehl
9
// Lese über SPI Ergebnis vom ADC Wandler ein und speichere in "ADC"
Hustle schrieb:> void loop() {> variable = 15; // Das ist der sich in jedem Loop wiederholende Befehl> // Lese über SPI Ergebnis vom ADC Wandler ein und speichere in "ADC"> Serial.print(variable * ADC);> Serial.print(variable + ADC);> }
So wird es formal jedes mal neu initialisiert, aber wahrscheinlich
wegoptimiert.
Wenn es nur einmal sein soll, dann:
1
voidloop(){
2
staticintvariable=15;// Das ist der sich in jedem Loop wiederholende Befehl
3
// Lese über SPI Ergebnis vom ADC Wandler ein und speichere in "ADC"
Hustle schrieb:> int variable, ADC;>> void lese_spi() {> ADC = ...;> }>> void loop() {> (1) variable = 15;> (2) lese_spi();> (3) Serial.print(variable * ADC);> (4) Serial.print(variable + ADC);> }
Globale Variablen sind immer Mist. In vielerlei Hinsicht. Nicht nur
ist es sehr schlechter Programmierstiel, auch werden viele Optimierungen
verhindert.
Der Grund? Mögliche Schreib-Zugriffe aus anderen Funktionen!
Dein Beispiel ist noch viel schlechter, als Du Dir im Moment vorstellst.
Grundsätzlich gilt bei solchen Sachen immer, wenn man sich unsicher ist:
Nachschauen/Ausprobieren/Messen. D.h. schau Dir das Assembler-Listing
verschiedenere Varianten an und lerne. So kommst Du vorwärts.
Zurück zum Problem.
a.) Zeile (1) kann nicht wegoptimiert werden, da 'variable'
global ist und z.B. jederzeit von anderen Funktionen
geschrieben und/oder gelesen werden kann.
b.) In Zeile (3) muss der Compiler die Variablen 'ADC' und
'variable' neu lesen, weil beide globalen Variablen
möglicherweise in 'lese_spi()' verändert wurden!
c.) In Zeile (4) wieder das gleiche. Der Compiler weiß nicht,
welche globalen Variablen in der Methode 'Serial.print()'
verändert wurden, also muss er hier wieder beide Variablen
'ADC' und 'variable' erneut lesen.
Bei globalen Variablen kann der Compiler praktisch kaum optimieren!
So wie es "Arduino Fanboy D. (ufuf)" vorgeschlagen hat, ist es richtig:
A. K. schrieb:> Der GCC ist bei Optimierung recht gut aufgestellt.> Er ist intelligent genug, Variablen ganz wegzulassen
offensichtlich, man unterschätzt die Fähigkeiten!
Ich habe gerade wieder ein Putz- & Aufräumphase in meinem Code, da fiel
mir eine ungenutzte uint32_t Var. auf.
Ich löschte diese und erwartete 4 freie Bytes mehr, Pustekuchen, der gcc
hatte sie wohl schon ignoriert oder rausgeworfen!
Experte schrieb:>> void lese_spi()
Könntest Du davon ausgehen, dass das Einlesen des ADC nicht durch eine
Funktion, sondern explizit programmiert an der Stelle
1
// Lese über SPI Ergebnis vom ADC Wandler ein und speichere in "ADC"
durchgeführt wird und dann eine Neubewertung der Optimierung vornehmen?
Ansonsten beantwortet sich meine Ursprungsfrage nicht.
Ich weiß, dass alles schlechter Programmierstil ist. Aber ich habe das
extra (schlecht) konstruiert, um die Frage nach der Wegoptimierung sich
im loop wiederholender Zuweisungen zu klären. Wenn jetzt der
Funktionsaufruf diese Optimierung verhindert, soll das Einlesen ohne
Funktionsaufruf sondern durch explizite Programmierung erfolgen.
Arduino Fanboy D. schrieb:> // ungünstig, eine magische Zahl mitten im Code
Das originale Programm ist komplexer und bedarf Kenntnisse von PLCs. Da
hätte die Diskussion im Forum um das originale Programm die eigentliche
Fragestellung der Optimierung in den Hintergrund gestellt. Deshalb soll
der konstruierte Code das Problem isolieren. Diese Isolation konnte ich
ohne schlechte Programmierung nicht hinbekommen.
Experte schrieb:> D.h. schau Dir das Assembler-Listing> verschiedenere Varianten an und lerne.
Gutes Stichwort! Wo in der Arduino Software kann ich den Assembler
sehen?
Hustle schrieb:> Wenn jetzt der> Funktionsaufruf diese Optimierung verhindert, soll das Einlesen ohne> Funktionsaufruf sondern durch explizite Programmierung erfolgen.
Der Funktionsaufruf an sich ist wahrscheinlich schon langsamer als diese
Zuweisung. Arduino ist sowieso nicht besonders effizient. Da willst du
wegen dieser 2-3 Takte das Programm schlechter lesbar machen?
Hustle schrieb:> Gutes Stichwort! Wo in der Arduino Software kann ich den Assembler> sehen?https://ucexperiment.wordpress.com/2012/02/21/arduino-assembly-language-listing-of-compiled-sketch-windows/
Hustle schrieb:> Experte schrieb:>> D.h. schau Dir das Assembler-Listing>> verschiedenere Varianten an und lerne.>> Gutes Stichwort! Wo in der Arduino Software kann ich den Assembler> sehen?
Das gibts so noch nicht, muss man in die Arduino IDE einbauen
Hier habe ich mal gezeigt, wie es geht:
Beitrag "Re: Welche Ressourcen nutzt die Arduino Software?"
Hallo
"Eine unveränderliche Variable, nennt sich Konstante.
...
Das Const kennzeichnet das Element als "read only".
Das verhindert ungewollte Veränderungen, bzw. schreit der Compiler, wenn
er bemerkt, dass du das versuchst.
Auch erlaubt das const setzen, dem Compiler weitergehende Optimierungen.
Soweit wie möglich, wird der Kompiler kein RAM für eine solche Konstante
reservieren, sondern den Wert direkt in den generierten Code
einflechten.
In dem Fall ist es natürlich egal wo die die Definition/Deklaration hin
schreibst."
Eine schöne Erklärung, die für Leute wie mich welche durchaus vertieftes
Wissen über die Hardware allgemein und den Grundlegenden Hardwareablauf
in einen µC und was generell mit erstellten Code "gemacht" wird bis er
als hex Datei in den µC geladen wird haben, aber nur wenig bis überhaupt
keine über die eigentlich Programmierung (in meinen Fall hatte) sehr
verständlich ist und so manche irgendwann ergebende Frage zu den warum
und wann bezüglich Konstanten und auch teilweise Variablen schon im
Voraus verhindert.
Was eine Konstante generell ist, ist einen (hoffentlich) noch aus den
Mathematikunterricht bekannt aber das genau warum und wie von Konstanten
in der µC Programmierung wird nur selten wirklich so klar und leicht
verständlich erklärt wie jetzt von dir.
Leider scheinen alle C, C++ und "Arduinoprogrammiertutorials" davon
auszugehen das man in der Programmierung schon vertiefte Grundkenntnisse
hat aber bezüglich der Hardware ein absoluter Anfänger ist.
Schade das es für Leute mit meinen (damaligen) Voraussetzungen kaum
Literatur und auch nur sehr wenig im Netz gibt und mann die wirklich
guten Erklärungen nur zufällig in Forenbeträgen oder manchmal halt recht
gut "versteckt" in irgendein Tutorial oder Buch findet.
Programmier Schüler