Forum: Mikrocontroller und Digitale Elektronik Werte schnell vergleichen


von Georg M. (g_m)


Lesenswert?

Momentan vergleiche ich die Länge von empfangenen Impulsen so wie es 
naheliegend ist:
1
// p: pulse length
2
// t: tolerance
3
4
if(p[i+1] < p[i] + t && p[i+1] > p[i] - t)
5
{ . . . . . . }

Aber geht es auch schneller?

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Je mehr man vom Kontext weiß, desto besser kann man optimieren... z.B. 
auch was für eine Zielplattform es ist.

von Georg M. (g_m)


Lesenswert?

> Zielplattform

8-Bit AVR mit 16-Bit TCB

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Georg M. schrieb:
>> Zielplattform
>
> 8-Bit AVR mit 16-Bit TCB

Na mit dieser Fülle an Informationen kann man sicherlich sagen: 
Schnelleren Controller nehmen hilft.

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


Lesenswert?

Georg M. schrieb:
> Aber geht es auch schneller?
Wie definierst du "schnell"? Wie sieht der aus diesem Code erzeugte 
Assembler aus? Wie ist p definiert und wie t? Welchen Optimierungslevel 
hast du eingeschaltet?

> if(p[i+1] < p[i] + t && p[i+1] > p[i] - t)
Ist diese if-Abfrage Teil einer Schleife mit ansteigendem i? Dann könnte 
man sich sparen, laufend immer wieder p[i] einzulesen, wenn man zuvor 
schon p[i+1] eingelesen hat. Zeig mal mehr vom Code.

> Aber geht es auch schneller?
Was ist "es", was willst du überhaupt machen?

: Bearbeitet durch Moderator
von Michael B. (laberkopp)


Lesenswert?

Georg M. schrieb:
> Aber geht es auch schneller?
1
abs(p[i+1]-p[i])<t
aber das benötigt auch 2 Vergleiche und ist damit genau so disruptiv, 
hoffentlich hat der Prozessor gute branch prediction.

Wenn der Prozessor Multiplikation in einem Takt schafft ist
1
(p[i+1]-p[i])^2<tsquared
eventuell schneller.

Kommt also immer auf die Hardware an.

Natürlich ist der indiziere Zugriff auf p optimierbar, aber das sollte 
der Compiler schaffen. Er wird auch die 2 Zugriffe pro Wert in deinem 
Original wohl durch Register optimieren, wenn der Prozessor davon 
genügende hat.

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


Lesenswert?

Michael B. schrieb:
> Natürlich ist der indiziere Zugriff auf p optimierbar, aber das sollte
> der Compiler schaffen.
Wenn da nicht noch irgendwie "zur Sicherheit, weil das ja in einer ISR 
verwendet wird" ein volatile davor steht.

Also Fazit: mehr vom Code zeigen (am besten in einem compilierbaren 
"Dreizeiler") und den erzeugten Assembler anschauen.

Michael B. schrieb:
> Kommt also immer auf die Hardware an.
Ist bekannt:

>> Zielplattform
> 8-Bit AVR mit 16-Bit TCB

: Bearbeitet durch Moderator
von Georg M. (g_m)


Lesenswert?

Lothar M. schrieb:
> Was ist "es", was willst du überhaupt machen?

Es geht mir primär nur um diese eine Zeile, ob sie irgendwie 
umgeschrieben werden kann, so dass das Ausführen schneller abläuft, auch 
wenn sich dadurch die Lesbarkeit des Codes verschlechtert.

Und wenn nicht, dann nicht. Dann bin ich beruhigt.

von Rainer W. (rawi)


Lesenswert?

Georg M. schrieb:
> Es geht mir primär nur um diese eine Zeile, ob sie irgendwie
> umgeschrieben werden kann, so dass das Ausführen schneller abläuft, auch
> wenn sich dadurch die Lesbarkeit des Codes verschlechtert.

Im Zweifelsfall kannst du direkt Assembler in den Code packen.
Bestimmt ist es überflüssig, sich jedes mal 4 Werte zu holen. Woher 
kommt t. Kann sich der ändern oder darf der vor dem Compiler auf einen 
festen Wert gesetzt werden?

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

Georg M. schrieb:
> Es geht mir primär nur um diese eine Zeile

Optimieren kann man das nur, wenn man mehr sieht.

- Ist eine Schleife drumherum?
- Wenn ja, ist p[i] der letzte Wert von p[i+1]? (Zwischenvariable)
- Wird p[i] - t und p[i] + t mehrfach gebraucht? (Register)
- Trifft öfter Bedingung 1 oder Bed. 2 zu? (short-circuit evaluation)
- Von welchem Typ sind p und i? (Array vs. Pointer)
- Ist t konstant? (Lookuptabellen)

Es gibt jede Menge möglicher Optimierungen, wenn man mehr drumherum 
sieht. Aber das scheint ja geheim zu sein.

: Bearbeitet durch Moderator
von Flunder (flunder)


Lesenswert?

Könnte sein, dass Loop-Unrolling was bringt, da dann aus p[i] eine feste 
Adresse wird.

Eventuell bringt schon das Arbeiten mit einem Pointer, der in der 
Schleife weiter geschoben (äh inkrementiert) wird, was. Beim Zugriff auf 
p[i], muss der Compiler ja den Wert von i mit der Größe eines Elements 
des Arrays multiplizieren.

von Axel S. (a-za-z0-9)


Lesenswert?

Georg M. schrieb:
> Es geht mir primär nur um diese eine Zeile, ob sie irgendwie
> umgeschrieben werden kann, so dass das Ausführen schneller abläuft
1
if(p[i+1] < p[i] + t && p[i+1] > p[i] - t)

Ach so. Na dann ist es einfach. Mach einfach vor dem && einen 
Zeilenumbruch. Dann läuft deine Zeile gleich doppelt so schnell.

"Tä-tä, tä-tä, tä-tä!" - "Wolle mer 'n rein lasse?"

Und jetzt mal ernst: kein Schwein versteht deinen Code nur vom Ansehen 
dieses einen Codeschnipsels. Ich vermute mal in p[] stehen irgend welche 
Samplewerte? Aber was soll t da im Vergleich?

: Bearbeitet durch User
von Udo S. (urschmitt)


Lesenswert?

Georg M. schrieb:
> Dann bin ich beruhigt.

Wenn das der einzige Grund für die Optimierung ist solltest du sie 
lassen.

Optimieren nur wenn es notwendig ist
In über 90% der Fälle geht Übersichtlichkeit vor einem kleinen 
Performancegewinn.
Außer bei Cloud systeme spart man nix, wenn der Prozessor nur 5% statt 
6% Auslastung hat.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Georg M. schrieb:
> Es geht mir primär nur um diese eine Zeile, ob sie irgendwie
> umgeschrieben werden kann

Das geht nur in seltenen Einzelfällen. Die Compiler optimieren die 
einzelnen Schritte schon sehr gut. Nur wenn man das Gesamtbild 
betrachtet kann man schon mal "Synergien" finden. Also z.B. Werte über 
mehrere Schleifendurchläufe wieder verwenden/durchreichen, anderen 
Algorithmus wählen, smartere Datenstruktur nutzen etc.

Bei größeren Controllern (z.B. Cortex-M4/7) geht manchmal was durch 
Nutzung von SIMD-Instruktionen.

Frank M. schrieb:
> Wird p[i] - t und p[i] + t mehrfach gebraucht? (Register)

Flunder schrieb:
> Eventuell bringt schon das Arbeiten mit einem Pointer, der in der
> Schleife weiter geschoben (äh inkrementiert) wird, was

Diese Dinge kriegen die Compiler tatsächlich meist schon selbst gut hin.

Udo S. schrieb:
> Außer bei Cloud systeme spart man nix, wenn der Prozessor nur 5% statt
> 6% Auslastung hat.

Bei Ultra-Low-Power Anwendungen kann das eventuell was bringen, wenn die 
Schleife wirklich dominant beim Energieverbrauch ist, und man vorher 
schon alles andere optimiert hat (Sleep Modi, CPU-Takt etc).

von Daniel A. (daniel-a)


Lesenswert?

Michael B. schrieb:
> Wenn der Prozessor Multiplikation in einem Takt schafft ist
> (p[i+1]-p[i])^2<tsquared
> eventuell schneller.

^ ist die xor Operation...

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


Lesenswert?

Georg M. schrieb:
> Es geht mir primär nur um diese eine Zeile, ob sie irgendwie
> umgeschrieben werden kann, so dass das Ausführen schneller abläuft, auch
> wenn sich dadurch die Lesbarkeit des Codes verschlechtert.
Lass das mal besser den Compiler machen. Der kann auf Maschinenebene 
optimieren. Da muss man nicht extra den ASCII-Code umsortieren, dass der 
kapiert, was man selber so meint, dass grade optimal wäre, sondern es 
reicht, ihm mitzuteilen, dass sich die verwendeten Variablen während des 
Programmablaufs nicht ändern können.

Es kommt eben wie gesagt darauf an, woher die zu vergleichenden 
Variabeln kommen und ob man sie in einem lokalen Register 
zwischenspeichern kann. Und dann kommt es eben auch noch drauf an, ob in 
der {} das Pointerregister auch noch gebraucht wird und wieder neu 
geladen werden muss usw. usf.

Evtl. ist aber schon die Abfrage Käse, wenn das unsigned TCNT-Register 
in den Bereich des Überlaufs kommt und man müsste gegen solche 
Überlaufprobleme sowieso den Code umschreiben (und dabei die richtigen 
Datentypen signed/unsigned nehmen):
1
if (p[i+1] < p[i] + t    &&    p[i+1] > p[i] - t)
2
-->
3
if (p[i+1] - p[i] < t    &&    p[i+1] - p[i] > -t)
Dann hättte man nur 1x die Rechnung p[i+1] - p[i]. Aber auch diese 
einfache Formelumstellung traue ich dem Optimierer inzwischen zu.

von Bruno V. (bruno_v)


Lesenswert?

Wichtiger als Geschwindigkeit ist Lesbarkeit und „es nicht zu 
verdaddeln“. Selbst auf kleinstem Prozessor nutze ich dafür eine Routine 
(nicht „inrange“ sondern between).

Verdaddeln wäre: volatile, Makro-Doppelauswertung, signed/unsigned, 
integral promotion, unsigned-Unterlauf, Und selbst dabei fahre ich oft 
harakiri und fange den signed-überlauf nicht korrekt ab, bzw. überlasse 
das der statistischen Codeanalyse

von Rainer W. (rawi)


Lesenswert?

Axel S. schrieb:
> Und jetzt mal ernst: kein Schwein versteht deinen Code nur vom Ansehen
> dieses einen Codeschnipsels. Ich vermute mal in p[] stehen irgend welche
> Samplewerte? Aber was soll t da im Vergleich?

DU verstehst es nicht.
Alleine schon der Kommentar "// t: tolerance" hilft.

von Michael B. (laberkopp)


Lesenswert?

Niklas G. schrieb:
> Die Compiler optimieren die einzelnen Schritte schon sehr gut

Du glaubst immer noch das Märchen 9

Daniel A. schrieb:
> ^ ist die xor Operation...

Nennt man Mathematik, verstehst du nichts von.

von Niklas G. (erlkoenig) Benutzerseite


Lesenswert?

Michael B. schrieb:
> Du glaubst immer noch das Märchen 9

Wir können nicht alle so erleuchtet sein wie du.

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.