Was ist schneller? AVR-GCC

#2468954
Lesenswert?

Hallo!

Für eine Berechnung habe ich drei Lösungswege. Welcher der Lösungswege 
ist der schnellste? Wie kann ich das ermitteln?

uint8_t panel;  // Panel-Nr. (0 bis 3)
uint8_t x;      // Spalte, in die geschrieben werden soll
uint8_t Col;    // Anzahl der Spalten je Panel

    panel = x / Col;   // Berechnung Panel-Nr.; für alle Lösungswege

1.  x -= Col * panel;

2.  x = x % Col;

3.  for(uint8_t i=0; i<panel; i++)
    {
      x -= Col;
    }

Für alle, die sowieso gleich fragen: Es geht um die Ansteuerung eines 
LED-Displays mit 96 x 16 Punkten.
Gast #2468973
Lesenswert?

Mess die Zeit oder guck dir den Code an, der vom Compiler erzeugt wird. 
Modulo ist aber generell ziehmlich langsam, außer wenn zur Compilezeit 
klar ist, dass nur modulo einer Zweierpotenz gerechnet wird.

Ich hatte für ein generiertes Muster, welches ich auf einem Display 
anzeigen wollte, Modulo-Operationen genutzt und der Bildaufbau war 
extrem langsam geworden.

Warum nicht einfach so:
1
if(++x >= Col) x = 0;
Gast #2468993
Lesenswert?

Hi

Außer Messen kannst du auch einfach mal überlegen, welche Operationen 
der Controller von Haus aus kann. Und das sind Addition, Subtraktion und 
bei den ATMegas noch Multiplikation. Das kann er am schnellsten. Also 
ist schon

> panel = x / Col;

nicht optimal. Aus Sicht eines notorischen Assemblerprogrammierers würde 
ich dir folgendes vorschlagen (Pseudocode):

panel = 0
while x >= Col
{
  x -= Col
  inc panel
}

Kommt ohne Division aus.

MfG Spess
#2469003
Lesenswert?

Tobi schrieb:
> Mess die Zeit oder guck dir den Code an, der vom Compiler erzeugt wird.
> Modulo ist aber generell ziehmlich langsam, außer wenn zur Compilezeit
> klar ist, dass nur modulo einer Zweierpotenz gerechnet wird.

Allerdings wird weiter oben eine Division der selben Werte durchgeführt, 
die den Rest eigentlich eh liefert. Aber ich meine, daß der gcc das 
nicht entsprechend optimiert. Vielleicht wäre da die Funktion div() 
sinnvoll. Die liefert gleich beides zurück.
Andererseits würde ich ganz auf die Division verzichten und eher sowas 
machen:
1
panel = 0;
2
while (x >= Col)
3
{
4
    panel++;
5
    x -= Col;
6
}

Edit: Mist, wieder mal zu langsam...
Gast #2469031
Lesenswert?

Hi

>Eben. Was alles für
>>x -= Col * panel;
>spricht.

Ja. Aber die 'Schnelligkeit' hat er sich schon mit 'panel = x / Col' 
versaut. Das muss in 'Software' gemacht werden. Deshalb mein Vorschlag, 
der Panel und x ohne diese Division berechnet.

MfG Spess
#2469042
Lesenswert?

Guido Scheidat schrieb:
> uint8_t Col;    // Anzahl der Spalten je Panel

Ist dies nicht eine Konstante? Dann würde ich es nicht als Variable 
definieren. Im Falle einer Konstanten kann der Compiler dies schon beim 
Compilieren berücksichtigen und muß es nicht zur Laufzeit machen.

Wie oft und wie wird diese Routine durchlaufen? Wie groß ist der Effekt 
auf das System?

Vielleicht kann man den Algorithmus anpassen und auf die Multiplikation 
verzichten indem dies iterativ erfolgt? Gilt zum Beispiel für den Fall 
das es aussenrum eine Schleife fürs panel von 0 nach 3 gibt.

Edit:
Peter Dannegger schrieb:
> bzw. sogar noch ne 2-er Potenz.

Nach seiner Angabe geht es um ein Display mit 96 Spalten und 4 Modulen, 
also müßte Col=24 sein.

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