Forum: Mikrocontroller und Digitale Elektronik C Code optimieren


von Heinz L. (ducttape)


Lesenswert?

Ich hab jetzt mal ein ASM-Projekt von mir in Richtung C geportet. Es 
wird langsam ein klein wenig groß um es weiter in ASM zu warten, also... 
ja, ich bin halt faul.

Nun bin ich nicht unbedingt der besten C Programmierer wenn's um 
Mikrocontroller geht. Also, entweder das oder die Optimierung vom AVR 
Studio ist unter aller Kritik, ich hab nicht mal die Hälfte der 
Funktionalität geportet, der Code ist inzwischen allerdings doppelt so 
groß, ebenso der Ramverbrauch. Das ist aktuell noch nicht so das 
Problem, allerdings scheine ich am Ende der Portierung mit knapp dem 
vierfachen Verbrauch an Flash und Ram dazustehen, und damit passt das 
Ding dann nicht mehr in einen Atmega8 und ich werd den 16er einbauen 
müssen. Etwas, das ich sehr gerne vermieden hätte.

Hab ich irgendwo 'n Optimierungsschalter übersehen oder stinkt der 
Optimierer vom AVRS wirklich so ab?

von meckerziege (Gast)


Lesenswert?

Zeile 42 ist das Problem.

von spess53 (Gast)


Lesenswert?

Hi

>und damit passt das
>Ding dann nicht mehr in einen Atmega8 und ich werd den 16er einbauen
>müssen. Etwas, das ich sehr gerne vermieden hätte.

Schon mal etwas von ATMega168/328 gehört?

MfG Spess

von Udo S. (urschmitt)


Lesenswert?

meckerziege schrieb:
> Zeile 42 ist das Problem.

Ja stimmt auf Spalte 42, das geht gar nicht!

von Ulrich (Gast)


Lesenswert?

Wenn man relativ gut in der ASM Programmierung ist, ist das nicht so 
ungewöhnlich wenn der C Compiler einen etwa 2 mal so langen Code 
erzeugt. Es hängt aber sehr vom Programm ab. Beim RAM braucht der 
Compiler ggf. etwas mehr, weil man In ASM gern ein paar Größen nur in 
den Registern hält und nie ins RAM schreibt.

von Karl H. (kbuchegg)


Lesenswert?

Heinz L. schrieb:

> Nun bin ich nicht unbedingt der besten C Programmierer wenn's um
> Mikrocontroller geht. Also, entweder das oder die Optimierung vom AVR
> Studio ist unter aller Kritik, ich hab nicht mal die Hälfte der
> Funktionalität geportet, der Code ist inzwischen allerdings doppelt so
> groß, ebenso der Ramverbrauch.

Zeig doch mal deinen Code.

> Hab ich irgendwo 'n Optimierungsschalter übersehen oder stinkt der
> Optimierer vom AVRS wirklich so ab?

Hast du denn den Optimierer überhaupt aufgedreht?

von Oliver (Gast)


Lesenswert?

Ulrich schrieb:
> Beim RAM braucht der
> Compiler ggf. etwas mehr, weil man In ASM gern ein paar Größen nur in
> den Registern hält und nie ins RAM schreibt.

Eben, aber der C-Compiler verbraucht nicht das doppelte an Ram. 
Allerdings muß man auch in C Konstanten explizit in den Flash legen, von 
alleine macht der Compiler das nicht.

Nur, das, was du in Zeile 42 gemacht hast, braucht 10-mal so viel Ram. 
Das geht wirklich gar nicht ...

Oliver

von Peter D. (peda)


Lesenswert?

Ulrich schrieb:
> Wenn man relativ gut in der ASM Programmierung ist, ist das nicht so
> ungewöhnlich wenn der C Compiler einen etwa 2 mal so langen Code
> erzeugt.

Es liegt eher daran, daß man in C noch nicht so geübt ist.
Man lernt C nicht an einem Tag. Zuerst wird man Wert darauf legen, daß 
erstmal die Ausdrücke synaktisch und funktional richtig sind.
Und später kann man sich den erzeugten Assembler ansehen, damit man es 
in C besser hinschreiben kann.

Hier gibt es auch einige Artikel, wie man dem C-Compiler die Arbeit 
leichter macht.
Verpönt sind z.B. unnötig große Variablen, globale Variablen, 
Spaghetticode statt Unterfunktionen.

Wenn man den Compiler auf nem 8Bitter alles in int rechnen läßt, was man 
in Assembler als Byte gerechnet hat, dann darf man sich auch nicht 
wundern, daß sich RAM und Code verdoppelt.

Compiler sind oftmals sehr schlau beim Optimieren, z.B. rechnen sie sehr 
gerne Konstanten schon zur Compilezeit aus. Man darf diese Konstanten 
nur nicht verschleiern, z.B. durch Übergabe per Pointer oder als 
Parameter.


Peter

von Heinz L. (ducttape)


Lesenswert?

Erst mal danke für die Antworten.

Es ist mir schon klar, dass keiner den Code "optimieren" kann wenn er 
ihn nicht sieht, das ist aber jetzt auch nicht das Thema. C ist nicht 
das Problem (eher schon die Heirat aus C und MC), ich programmier seit 
rund 15 Jahren in C, auch für Kohle, ich behaupte mal, inzwischen hab 
ich ein wenig davon verstanden. ;) Und was ich da bisher geschrieben 
habe ist auch nicht viel mehr als einmal Standard zum Mitnehmen ohne 
Fritten.

Die Variablen sind durchwegs uchars, sofern ich nicht unbedingt und 
absolut mehr brauche. Eine Handvoll shorts sind dabei und eine long (die 
wegen der Genauigkeit existiert, um erst multiplizieren und dann 
dividieren zu können und damit ganzzahlig zu bleiben und nicht auch noch 
Fließkomma rechnen zu müssen). Die tun aber ehrlich gesagt weniger weh, 
sind einige Instruktionen, nichts was jetzt Welten bewegen würde, 
außerdem gab es ganz ähnliche Konstrukte auch in dem ASM Code (dort war 
diese 32-bit Long allerdings auch in den Registern problemlos 
unterzubringen, so lang brauch ich sie ja nicht dass ich dafür Ram 
verschwenden müßte). Das kann mir nun den Ram-Verbrauch nicht so 
aufblähen.

Und ja, bisher habe ich MC hauptsächlich in ASM programmiert, und 
normalerweise unter sehr umfangreicher Registerschieberei, und wenn das 
nicht reicht ist der Stack ja auch noch da. Ram habe ich da tatsächlich 
nur für "echte" Variablen benötigt die Daten länger als ein paar 
Instruktionen halten sollen.

Mein Thema ist mehr AVRStudio. Weil ehrlich gesagt, damit hab ich mich 
weniger beschäftigt. War für ASM nicht soooo notwendig, aber für C 
scheint's da umfangreichere Schalter zu geben. Entsprechend die Frage 
was man denn da noch drehen kann um zu optimieren. Die einzige 
Optimierungsoption die ich kenne ist die über die Properties - 
Optimization. Damit krieg ich zwar den Code wieder in ein normales Maß 
eingedampft (gut, immer noch doppelte Größe, aber zumindest nicht 
vierfache), ich brauch aber für die paar Dinge bereits 24% vom Ram vom 
ATmega16. Mein gesamter ASM code verballert grad mal 13%. Und auch 
wenn's jetzt blöd und "unnötig" klingt wegen der paar Speicherstellen zu 
jammern, ich optimiere gerne so weit dass ich erstens einen kleineren MC 
verwenden kann und zweitens noch Platz für Erweiterungen hab.

Gibt's noch etwas das man einstellen kann oder hat jemand Tips (oder 
vielleicht sogar 'n Link zu Optimierungstips)? Die "üblichen" 
Optimierungen die man auch bei Programmen für "ausgewachsene" Computer 
ansetzen kann kenn ich ja. Was mir fehlt sind die Feinheiten und Quirks 
des MC C.

von Karl H. (kbuchegg)


Lesenswert?

Noch mal langsam zum mitschreiben.

 Z E I G E    D E N     C O D E   !


µC programmieren sich in einigen Bereichen etwas anders als PC.

Und nein: Ein Faktor 2 ist im Code nicht normal. Normal sind 10 bis 20% 
plus ein mehr oder weniger immer gleicher konstanter Anteil. Vielleicht 
geht es auch mal auf 30% hoch, aber Faktor 2 ist zu viel.

Beim SRAM. Soviele Daten du hast, soviel Speicher brauchst du auch. Auf 
C Ebene gibt es für dich als Programmierer keine Register mehr. Jede 
Variable lebt erst mal grundsätzlich im SRAM. Der Compiler wird 
versuchen, Variable über weite Strecken in Registern zu halten, aber er 
braucht grundsätzlich für jede Variable einen Platz im SRAM, wohin er 
sie auslagern kann. Einzige Ausnahme: Wenn er sie komplett wegoptimieren 
kann.

Und nein: Für nicht benutzten Speicher gibt es kein Geld zurück.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Heinz L. schrieb:
> Mein Thema ist mehr AVRStudio.
Der dort verwendetet Compiler ist der GCC. Mit dem AVR-Studio bastelst 
du (vereinfacht geasgt) nur die Kommandozeile für den Compiler zusammen.

Heinz L. schrieb:
> ich brauch aber für die paar Dinge bereits 24% vom Ram vom ATmega16.
Konstante Texte, die du in Assembler automatisch ins Flash legst, 
bedürfen in C einer besonderen Syntax. Wenn du einfach nur schreibst
char meintext[6] = "Hallo";
Dann braucht dieser Text 6 Bytes im ROM (für die Initialisierung) und 6 
Bytes im Ram (weil Variable erst mal ins RAM kommen).

Heinz L. schrieb:
> Und auch wenn's jetzt blöd und "unnötig" klingt wegen der paar
> Speicherstellen zu jammern, ich optimiere gerne so weit dass ich
> erstens einen kleineren MC verwenden kann und
Der aber gar nicht so arg viel billiger ist...
> zweitens noch Platz für Erweiterungen hab.
Die dann wieder viel Hirnschmalz und Gewürge erfordern, damit sie noch 
reinpassen. Ich nehm dann, wenn die "übliche" Vorgehensweise (ohne die 
traditionellen Fehler) den uC zu sehr ausreizt, einfach den 
nächstgrößeren...

Aber grundsätzlich ist es natürlich bedenklich, wenn du doppelt soviel 
RAM wie erwartet verbrauchst und nicht weißt, warum. Denn dann geht da 
gerade irgendwas schief...

von Volkmar D. (volkmar)


Lesenswert?

Heinz L. schrieb:
> ich brauch aber für die paar Dinge bereits 24% vom Ram vom
> ATmega16. Mein gesamter ASM code verballert grad mal 13%.

Hast Du Dir denn mal die Ausgabe vom GCC angeschaut und verglichen wofür 
das RAM benutzt wird? Meistens bekommt man damit schon Ideen in welche 
Richtung man schauen muß bzw. kann hier konkret fragen.

Volkmar

von Udo S. (urschmitt)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Noch mal langsam zum mitschreiben.
>
>  Z E I G E    D E N     C O D E   !

Genau!
Wir können nicht sehen ob du irgendwelche umfangreichen Bibliotheken für 
Arithmetik benutzt, oder du nur wegen einer Stringkopiererei dir mit 
sprintf() einen dicken Batzen Code dazulinkst.
Bzgl. Variablen. Hast du alle nicht global benötigten auch lokal in 
Funktionen angelegt oder alles global deklariert?
....

Die Fragen sind endlos, einzig sinnvolles:

Karl Heinz Buchegger schrieb:
>
>  Z E I G E    D E N     C O D E   !

von Peter D. (peda)


Lesenswert?

Beim AVR-GCC werden konstante Strings auch im RAM abgelegt. Es gibt zwar 
einen Würg-Around mit Macros für Flash-Arrays, aber das wird schnell 
unleserlich und schaltet auch wichtige Typprüfungen ab.
Insbesondere bei Structs ist es kompliziert, den Code zum Laufen zu 
bringen. Die standard Operatoren z.B. a.c->d[e] lassen sich nicht 
verwenden und man muß die Adreßrechnung zu Fuß machen.

Ich hab mir das für die meisten Verwendungen wieder abgewöhnt und lasse 
zugunsten der besseren Programmierbarkeit und Lesbarkeit die Konstanten 
im RAM. Es gibt ja inzwischen auch AVRs mit viel RAM, z.B. ATmega1284P.

Nur für wirklich große Tabellen, z.B. Zeichensätze eines GLCD mache ich 
mir die Qual mit den Flash-Konstanten.


Peter

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Heinz L. schrieb:
> Mein Thema ist mehr AVRStudio. Weil ehrlich gesagt, damit hab ich mich
> weniger beschäftigt. War für ASM nicht soooo notwendig, aber für C
> scheint's da umfangreichere Schalter zu geben.

Du hast noch nichtmals geschrieben, welche Optimierungsstufe Du 
verwendest. Diese sollte -Os sein, steht zum Beispiel im C-Tutorial.

Alles andere hier ist bloße Raterei. Ohne C-Code kann man nichts weiter 
dazu sagen.

von Oliver (Gast)


Lesenswert?

Etwas mehr dazu gibt es hier, aber das hast du bestimmt schon gelesen ;)

http://www.mikrocontroller.net/articles/AVR-GCC-Codeoptimierung#GCC-interne_Optimierung

Riesige Sprünge gegenüber -Os bringt das aber nicht mehr.

Oliver

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.