Forum: Compiler & IDEs Verständnisproblem: Programgröße ändert sich mich Wert des shift-Faktors


von Santiago (Gast)


Lesenswert?

Hallo,

ich habe in einer header-Datei ein Define für die Korrektur der 
Encoderschritte.
Ich habe 2 versch. Encoder, von denen die eine Sorte 2 Pulse pro Raste 
liefert, die andere 4 Pulse pro Raste.

Bei der Bearbeitung des Menüs wird der Zähler jeweils um den Betrag 
verschoben (also einmal >> 1 und das andere Mal >> 2).
Das ganze ist mir nur aufgefallen, weil ich gerade bei +- 100% 
Auslastung einer Tina bin und mit jedem Byte geizen muss.

Ändere ich den Wert von 2 auf 1 steigt die Programmgröße um 10-12 Byte 
und ist plötzlich über 100% (mit Optimierung -Os). Ändere ich den Wert 
wieder zurück auf 2 sinkt die Programmgröße um obige Anzahl Bytes.

Wieso ändert sich die Codegröße in Abhängigkeit des shift-Faktors?

Kann ich den Code umformulieren, sodass diese Effekte nicht mehr 
auftreten?

von egberto (Gast)


Lesenswert?

das liegt am Optimierer...vereinfacht gesagt, wenn z.B. ein Register 
schon mit z.B. 2 vorgeladen ist, und die nächste Operation dort 2 
benötigt - wird kein Platz verbraucht, ist es mit 5 belegt, gehen ein 
paar Byte für die Umbelegung drauf..

Besonders deutlich ist das auch, wenn man Variable mal mit 0 und mal mit 
was anderem belegt.

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


Lesenswert?

Santiago wrote:

> Wieso ändert sich die Codegröße in Abhängigkeit des shift-Faktors?

Weil deine Tina offenbar ein Prozessor ist, der keine N Bits in
einem Befehl schieben kann, sondern nur jeweils um 1 Bit.

von Stefan E. (sternst)


Lesenswert?

Jörg Wunsch wrote:

> Weil deine Tina offenbar ein Prozessor ist, der keine N Bits in
> einem Befehl schieben kann, sondern nur jeweils um 1 Bit.

Aber die Größenänderung ist "verkehrt herum". ;-)

von Santiago (Gast)


Lesenswert?

> Weil deine Tina offenbar ein Prozessor ist, der keine N Bits in
> einem Befehl schieben kann, sondern nur jeweils um 1 Bit.

Hm - nach der Logik würde ich aber bei dem größeren Schiebewert den 
größeren Code erwarten. Es ist aber genau anders herum.

Da klingt die Variante von "egberto" plausibler.
Das ist aber bitter, wenn die Codegröße vom Zufall, bzw. von der 
initialen Registerbelegung abhängt.

von Andreas K. (a-k)


Lesenswert?

Ohne den konkreten Code testen zu können ist das alles nur 
Kaffeesatzleserei.

Wenn es wirklich wichtig ist, die Länge(!) des Code unabhängig von der 
Shift-Count zu machen, musst du nur dafür sorgen, dass dieser Wert vom 
Compiler nicht als konstant angesehen wird. Dann wird eine Schleife 
draus. Für die Laufzeit ist das natürlich ein Schuss in den Ofen, und 
die ist dann statt der Länge davon abhängig. Wenn du sowohl Laufzeit wie 
Länge konstant und kurz halten willst, musst du von AVR Abschied nehmen.

von Peter D. (peda)


Lesenswert?

Santiago wrote:

> Kann ich den Code umformulieren, sodass diese Effekte nicht mehr
> auftreten?

Ja.

Es gibt keinen Code, der sich nicht noch weiter optimieren ließe.

Um mehr zu sagen, müßtest Du den Code mal zeigen.


Peter

von Santiago (Gast)


Lesenswert?

Hallo,

danke für Eure Aufmerksamkeit.

> Ohne den konkreten Code testen zu können ist das alles nur
> Kaffeesatzleserei.

Ist leider eine Auftragsarbeit - kann ich nicht so einfach posten.

@Peter
Jetzt bin ich genau an dem Punkt, den ich befürchtet hatte. Die 
Umrechnerei der Encoder Pulse bricht mir das Genick.
Leider bekam ich keine Antwort auf meine Frage nach einem Encoder, der 
nur einen Puls pro Raste erzeugt.

Nur aus Spaß habe ich den ganzen Umrechnungscode mal gekapselt und die 
Auswirkungen liegen bei ca. 100 Byte Codegröße. Das halte ich für eine 
Tina recht üppig und nimmer vernachlässigbar.

> Es gibt keinen Code, der sich nicht noch weiter optimieren ließe.

Yep - aber in 2 Tagen habe ich kein Assembler gelernt :(
Wird also schweren Herzens ein mega und damit ne neue Platine werden 
müssen.

von Oliver (Gast)


Lesenswert?

Auch wenns eine Auftragsarbeit ist, lässt sich doch bestimmt daraus ein 
kürzeres Testprogramm stricken, das den Effekt zeigt, und das du hier 
zeigen kannst.

Wenn nicht, must du halt alleine weiter basteln.

Oliver

von Peter D. (peda)


Lesenswert?

Santiago wrote:
> Nur aus Spaß habe ich den ganzen Umrechnungscode mal gekapselt und die
> Auswirkungen liegen bei ca. 100 Byte Codegröße. Das halte ich für eine
> Tina recht üppig und nimmer vernachlässigbar.

Was ist eine Tina?

Die ATtiny haben ja alle außer dem ATtiny2313 bis zu 8kB Flash, da sind 
100 Byte pillepalle.


> Yep - aber in 2 Tagen habe ich kein Assembler gelernt :(

Wer hat was von Assembler gesagt?
Es geht erstmal um die Optimierung des C-Codes.
Natürlich wäre es schön, wenn man dazu das Listing des Compilers 
versteht.
Aber Bytes zählen kann man auch ohne Assemblerkenntnisse.


Peter

von egberto (Gast)


Lesenswert?

Wenn du bis jetzt "normal ordentlich" programmiert hast, d.h. kein 
besonderes Augenmerk auf die Codegröße gelegt hast, sind mit der hier 
verfügbaren Anleitung zur Codeoptimierung in C bestimmt noch 100 Byte zu 
holen.
Ein weiterer "Geheimtip": nimm einen etwas älteren GCC (von 2006/2007).

Viel Erfolg

von Matthias (Gast)


Lesenswert?

Also ein wenig Inline Assembler könnte da Wunder wirken. Wenn man 
allerdings erstmal richtig Assembler Programmieren lernen muss, dann 
siehts da düster aus.

Ich hatte mal eine Erfahrung mit nem Tiny 2313. Mit C-Code 100% bzw. zu 
groß
für den Flash für die gewünschte Funktion. Hab mich dann dazu 
entschlossen, anhand des C-Codes alles in Assembler selber zu schreiben 
(C-Code allerdings als Blaupause"). Und siehe da alles passt rein: 
Optimierung um 50% -> Also
Controller Flash zu 50% voll. Man muss allerdings sehr viel mehr 
Hirnschmalz
investieren, da die üblichen Komfortfunktionen des Compilers wegfallen.
Und größere Arrays mit ihrer Indizierung schnell schief gehen können!

von Santiago (Gast)


Lesenswert?

@Oliver
1
#define FAKTOR 1
2
3
a = b >> FAKTOR;
So sieht der code aus - natürlich in 2 verschiedenen Dateien.
Von den Zählerzuweisungen gibt es einige (glaube 5).
Wenn ich FAKTOR auf 2 setze ist der Code kleiner als wenn ich ihn auf 1 
setze.

Aber ok - wir können es dabei belassen.

Dank Euch für Eure Zeit und Aufmerksamkeit.

@Peter
> Die ATtiny haben ja alle außer dem ATtiny2313 bis zu 8kB Flash, da sind
> 100 Byte pillepalle.

Nun es war genau die ATtiny2313.

Aber wie heißt es so schön: aus Schaden wird man kluch ;)

@egberto
> Wenn du bis jetzt "normal ordentlich" programmiert hast, d.h. kein
> besonderes Augenmerk auf die Codegröße gelegt hast, sind mit der hier
> verfügbaren Anleitung zur Codeoptimierung in C bestimmt noch 100 Byte zu
> holen.

Nun ich bin neu in der mC-Programmierung. Allerdings habe ich schon auf 
Speicherbedarf geschaut. Wie gut ich dabei war, kann ich jetzt nicht 
beurteilen. Ich werd's mir nochmal anschauen. Danke für das 
"Mut-machen".
Wahrscheinlich wird es doch auf einen anderen Chip rauslaufen.

von Santiago (Gast)


Lesenswert?

@Matthias
Wir sind uns einig, dass mit Assembler noch einiges rauszuholen wäre.
Nur habe ich im Moment nicht die Zeit, mich da auch noch einzuarbeiten.
Ich bin mir ziemlich sicher, dass der Aufwand alle Erwartungen sprengt.

Ein ander Mal vielleicht.

von Peter D. (peda)


Lesenswert?

Santiago wrote:

> Nun es war genau die ATtiny2313.
>
> Aber wie heißt es so schön: aus Schaden wird man kluch ;)

Ja, ich habe mich auch schon mächtig geärgert, daß Atmel alle ATtiny auf 
8kB/512B gepimmt hat, aber bloß den ATtiny2313 nicht.

2kB ist wirklich so die kritische Grenze für den AVR-GCC, man ist 
ruckzuck drüber.

Ich versuche daher neue Projekte auf den ATtiny461/861 umzuschwenken. 
Der hat zwar 2 IOs weniger, aber mit Bootloader kann man alle 16 
benutzen.


Peter

von Andreas K. (a-k)


Lesenswert?

Peter Dannegger wrote:

> 8kB/512B gepimmt hat, aber bloß den ATtiny2313 nicht.

Wahrscheinlich streiten sie nun schon sein Jahren über den dafür zu 
vergebenden Namen. Passt halt nicht ins Schema. ;-)

von Oliver (Gast)


Lesenswert?

>Von den Zählerzuweisungen gibt es einige (glaube 5).

Solange da nicht auch 5 Drehgeber an der Tina hängen, könnte man 
schonmal fragen, warum gerade 5, und nicht nur genau eine pro Drehgeber?

Oliver

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Santiago wrote:
> @Oliver
>
1
> #define FAKTOR 1
2
> 
3
> a = b >> FAKTOR;
4
>
> So sieht der code aus - natürlich in 2 verschiedenen Dateien.
> Von den Zählerzuweisungen gibt es einige (glaube 5).
> Wenn ich FAKTOR auf 2 setze ist der Code kleiner als wenn ich ihn auf 1
> setze.
>

Möglicherweite merkt sich der Compiler Zwischenwerte und braucht mehr 
Register, was dann einen Frame erfordert.

Ohne asm-Listing/C-Quelle/Compiler-Version/Schalter ist's aber 
Rumgestochere. Möglich auch, daß GCC erkennt, daß b eine Konstante ist 
und dadurch Optimierungen machen kann für >> 2, die er für >> 1 nicht 
machen könnte, zB wenn dadurch ein if(a == ...) Block wegfällt da toter 
Code.

Einige "Optimierungen" kann man abwürgen, indem man vor/hinter C-Befehle 
schreibt

asm volatile (""::);

oder indem man GCC explizite Kenntnis über Registerinhalte nimmt:

asm volatile ("" : "+r" (a));

Beide Templates gehen für alle GCC-Varianten, also nicht nur für AVR. 
Sie erzeugen keinen Code, haben aber Einfluss aufs Compilat.

Nochwas zu "C-Quelle"

Bei einem aggressiv optimierenden Compiler ist immer auch der 
Gesamtkontext einer Codezeile wichtig. Eine losgelöste Zeile kann 
komplett anderen Code erzeugen als im Kontext. Auch wenn nur eine 
kleine, unscheinbare Codeänderung in der C-Quelle gemacht wird, kann das 
dennoch Auswirkungen darauf haben, wie C-Code 100 Zeilen davor(!) oder 
dahinter compilert wird!

von Santiago (Gast)


Lesenswert?

> Ich versuche daher neue Projekte auf den ATtiny461/861 umzuschwenken.
> Der hat zwar 2 IOs weniger, aber mit Bootloader kann man alle 16
> benutzen.

Hm - habe mir die Steinchen mal angeschaut, die MLF-Varianten scheinen 
gleich groß mit dem mega8 zu sein. Warum dann nicht gleich den mega9 
nehmen?
Preislich sind die 8er tiny nicht gerade interessant.

> Solange da nicht auch 5 Drehgeber an der Tina hängen, könnte man
> schonmal fragen, warum gerade 5, und nicht nur genau eine pro Drehgeber?

Klar darf man(n) fragen!

Ich habe eine vorgegebenen Kommunikationsstruktur zu füllen. Die Zähler 
sind unterschiedlich breit (zwischen 1 und 6 Bit). Ursprünglich hatte 
ich die Werte direkt in der Struktur verändert, aber auf Anraten Iflands 
verwende ich einen separaten Zähler für die Werte. Entgegen der Prognose 
vergrößert das den Code nicht unerheblich.
Vor der Übertragung müssen die dann aufs richtige Maß geschoben werden.
Ach ja, die Zähler werden "gleichzeitig" oder auch atomar übertragen, 
deshalb kann ich nicht einen Zähler für alle nehmen.

> Eine losgelöste Zeile kann komplett anderen Code erzeugen als im Kontext.

Ja, das hatte ich bereits in einem anderen Fred. Dort hatte ich einen 
Fehler in der Initialisierung, der erst nach Posten des gesamten Codes 
rauskam.

Die Tips zur Beeinflussung der Optimierung sine sehr interessante 
Konstrukte. Werde per Gelegenheit die Auswirkung mal ausprobieren. 
Danke.

Habe inzwischen auch die Anleitung zur Codeoptimierung gefunden und 
gelesen. Die meisten Punkte waren mir bekannt und ich hatte sie bereits 
beachtet (ich hatte mal die entsprechende Appnote von Atmel gelesen).

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.