Allgemeine Codeoptimierung in C für uC

OP #3022388
Lesenswert?

Hallo Forum,
ich weiss jetzt nicht in welches Forum das rein sollte, da es um 
Programmieren und um uCs geht.
Ich wollte mal allgemein fragen ob jemand Tipps oder gute Seiten im Netz 
kennt, wo es darum geht, wie man Programmcode optimieren/verbessern 
kann. Ich finde dazu leider keine passenden Seiten und wenn dann geht es 
meist um JAVA.
Ich weiss zum Beispiel, dass es sinvoller ist statt "/2" zu rechnen, die 
Bitverschiebung ">>1" zu nutzen, da man hierbei Zeit spart.
Gast #3022398
Lesenswert?

Sa We schrieb:
> Ich weiss zum Beispiel, dass es sinvoller ist statt "/2" zu rechnen, die
> Bitverschiebung ">>1" zu nutzen, da man hierbei Zeit spart.

Und nichtmal das stimmt für alle Plattformen.

Das Beste ist, plattform- und compilerunabhängigen Code zu schreiben. 
Die Optimierung kann man dann ruhig dem Compiler überlassen. Nur wenn es 
unumgänglich ist kann/muss man von dieser Regel abweichen. Beispiele 
sind Startup-Code, Hardware-/Registerzugriffe oder extrem zeitkritische 
Sachen - wobei letzteres ein Streitpunkt ist, da oft ein Denkfehler 
und/oder schlechte SW-Archtitektur zugrunde liegt, wenn man das machen 
muss...
#3022407
Lesenswert?

Sa We schrieb:

> Ich weiss zum Beispiel, dass es sinvoller ist statt "/2" zu rechnen, die
> Bitverschiebung ">>1" zu nutzen, da man hierbei Zeit spart.

Und du denkst echt, Compilerbauer hätten in 50 Jahren nicht gelernt, wie 
man sowas einem Compiler beibringen kann?

PS: Im übrigen stimmt das gar nicht.
Rechne mal   -3 / 2  und dann vergleichst du mit dem Ergebnis von -3 >> 
1
:-)
Compiler wissen nämlich auch das: unter welchen Umständen ist eine 
derartige Optimierung überhaupt möglich.
#3022454
Lesenswert?

Sa We schrieb:

> Ich dachte eben, dass es so bestimmte Dinge gibt, die man eben allgemein
> von vornherein beachten sollte, die man eventuelle aus eigener Erfahrung
> weiss.

Schreib den Code so, dass er gut lesbar, wartbar und übersichtlich ist.
Verwende den kleinsten Datentyp der angemessen ist
Verwende einen angemessenen Algorithmus
Kenne dein Werkzeug - die Programmiersprache


Und um den Kleinscheiss: lass den den Compiler erledigen.

Wenn dann dein Programm nachweislich zu langsam ist, dann fange mit 
Optimierungen an, wobei du zuerst auf der hohen algorithmischen Ebene 
nach Verbesserungen suchst. Wenn da wirklich alles ausgereizt ist, dann 
profile deinen Code, um die Stellen zu finden, an denen das Bottleneck 
sitzt. Sieh dir dort den Assemblerteil an und versuch ein wenig 
nachzuvollziehen, wie sie mit diesem konkreten Compiler entstanden sind. 
Überleg, welches C-Konstrukt wohl den Compiler von anderer Optimierung 
abgehalten hat. Versuch dann, den C-Code so zu verändern, dass sich dem 
Compiler andere Optimierungen ermöglichen.

Aber in der überwiegenden Mehrzahl der Fälle ist ein sauber und nicht 
blödsinnig pessimiertes C-Programm aus der Box heraus schnell genug. 
Optimiere nicht zusätzlich, wenn du nicht musst. Ist ein Programm 
schnell genug, dann reicht das. Dazu gehört auch, dass man die zu 
erzielenden Grenze "wann ist es schnell genug" kennt.

Optimierungen beginnen beim Algorithmus. Auch der am besten auf 
Assembler-Ebene optimierte Bubble-Sort wird selbst gegen den lausigsten 
Quick-Sort bei hinreichenden Datenmengen immer das nachsehen haben.

Bis auf ganz wenige Ausnahmen: Speed holt man sich nicht dadurch, dass 
man 2 Befehle auf Assembler-Ebene durch eine trickreiche C-Schreibweise 
einspart. Und wenn du soweit bist, dass du diese 2 Takte tatsächlich 
brauchst, dann hast du auch genug gelernt um zu wissen wie und warum man 
welche Änderung macht und wie sich die im Assemblercode auswirkt.
Gast #3022479
Lesenswert?

Kommt drauf an, wass du optimieren willst.
Wenn du z.B. auf einem AVR unterwegs bist, dann ist es für die 
ausführungszeit besser wenn du:
1
for(unsigned char i=0; i<255; i++)
2
{
3
  for(unsigned char j=0; j<255; j++)
4
  {
5
    //tu was
6
  }
7
}

als:
1
for(unsigned int i=0; i<64516; i++)
2
{
3
  //tu was
4
}
schreibst. Die zwei for-Schleifen sind einfach schneller.

Hängt aber eben davon ab, was du wo und wie machen willst.
Gast #3022612
Lesenswert?

Für den (automotive) embedded Bereich gibt es die MISRA Regeln für "C".
Wenn man die befolgt, sind automatisch schon etliche 
ortimierungsfördernden Dinge erledigt.
Den Rest bzw. die Optimierung selbst macht der Compiler.
Bei hoher (guter) Optimierungseinstellung wird beispielsweise bei /2 und 
>>1 identischer .hex bzw. Binärcode rauskommen.
Wichtig ist: Größe der Variablen beachten, implizite cast vermeiden 
(also cast selbst hinschreiben wo erfoderlich, schon zur Klarheit) und 
float ganz meiden, ausser in #define oder Berechnungen wo resultierend 
eine Konstante als Integer rauskommt.

Klaus
#3023076
Lesenswert?

Erich schrieb:
> Bei hoher (guter) Optimierungseinstellung wird beispielsweise bei /2 und
> >>1 identischer .hex bzw. Binärcode rauskommen.
Gerade hier muss man aber aufpassen. Bei Rechts-Shift arbeitet ein 
C-Compiler vorzeichenkorrekt. Ein vorzeichenloser Datentyp erhält im 
obersten Bit beim rechtsschieben immer eine 0, ein vorzeichenbehafteter 
Datentyp bekommt das vorletzte Bit.
Das Beispiel von Karl Heinz weist in die richtige Richtung:
-3/2 ergibt -1, -3>>1 ergibt -2.

Kleines Dummy-Programm mit Debug-Ausgabe dazu:
1
    unsigned char a=-3;      // impliziter Type-Cast
2
    signed char b=-3;
3
    Ergebnis = a;            // 0xFD = Zweierkomplement von -3, 
4
    while(1)                 // wird jetzt aber als +253 interpretiert
5
    {
6
        if(P3_2)
7
            Ergebnis = a/2;  // 0x7E
8
        else
9
            Ergebnis = a>>1; // 0x7E
10
        if(P3_3)
11
            Ergebnis = b/2;  // 0xFF
12
        else
13
            Ergebnis = b>>1; // 0xFE
14
    }

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren