Schnellere Division

Gast #4692006
Lesenswert?

Hallo

Ich programmiere einen ATmega mit Hilfe des AVR Studios.
Mich würde interessieren, welcher Rechenschritt auf dem µC schneller ist 
und warum.

20 / 5;

oder

20 >> 4;

Kann der µC mit den Schiebebefehlen schneller arbeiten? Und wie genau 
würde er die Division ausführen?
Gruß.
Gast #4692016
Lesenswert?

Baum2 schrieb:
> Mich würde interessieren, welcher Rechenschritt auf dem µC schneller ist

warum simulierst du es dann nicht einfach?


20 / 5;
20 >> 4;

Da kommt eh nicht das gleiche Raus, was willst du das vergleichen?

> Kann der µC mit den Schiebebefehlen schneller arbeiten?
meist ja, genauere steht im Datenblatt
Gast #4692025
Lesenswert?

Peter II schrieb:
> Baum2 schrieb:
> Mich würde interessieren, welcher Rechenschritt auf dem µC schneller ist
>
> warum simulierst du es dann nicht einfach?
>
> 20 / 5;
> 20 >> 4;
>
> Da kommt eh nicht das gleiche Raus, was willst du das vergleichen?

Es geht mir um die Rechenschritte die er benötigt.
#4692032
Lesenswert?

Baum2 schrieb:
> Hallo
>
> Ich programmiere einen ATmega mit Hilfe des AVR Studios.
> Mich würde interessieren, welcher Rechenschritt auf dem µC schneller ist
> und warum.
>
> 20 / 5;
>
> oder
>
> 20 >> 4;
>
> Kann der µC mit den Schiebebefehlen schneller arbeiten? Und wie genau
> würde er die Division ausführen?
> Gruß.

Entscheidend ist, was der Compiler aus Deinem Code macht. Sehr 
wahrscheinlich wird er es so umsetzen, dass es keinen Vorteil bringt im 
Code einen Shift-Befehl hinzuschreiben anstatt einer Division.
Moderator Persönliche Seite #4692038
Lesenswert?

Peter II schrieb:
> Eine Division durch 1 geht z.b. sehr schnell.

… gefolgt von einer Division durch ganze Zweierpotenzen.

Konstante Divisionen taugen natürlich sowieso nicht für den Vergleich,
denn die werden vom Compiler rausoptimiert.  Divisionen durch konstante
Zweierpotenzen werden typisch ebenfalls ohne Bibliotheksaufruf durch
passende Schiebeoperationen bereits vom Compiler ersetzt.
Gast #4692040
Lesenswert?

Baum2 schrieb:
> Es geht mir um die Rechenschritte die er benötigt.

Schreibe dir ein Mini-Programm das auf dem einen und
dem anderen Weg die gleiche Rechnung durchführt.
Compiliere es und schaue dir das vom Compiler erzeugte
*.lss file an. Dort kannst du auf Asssembler-Ebene
nachvollziehen was der Prozessor tun soll.

Allerdings solltest du die Optimierung ausschalten da
der Compiler eventuell für beide Rechenwege die
gleiche Methode wählt.
#4692068
Lesenswert?

Dirk_Geber schrieb:
> Ich würde halt gerne wissen, ob es im Bezug auf die Optimierung
> sinnvoller ist, nur durch Zweierpotenzen zu dividieren.

Zuerst einmal will man in aller Regel korrekte Ergebnisse haben. Also 
führt man eben die Berechnungen aus, die notwendig sind um das 
gewünschte Ergebnis zu bekommen.

Ich habe noch von keiner realen Anwendung gehört, in der man sich das 
korrekte Dividieren aus Performance-Gründen komplett verkneifen musste.
Gast #4692078
Lesenswert?

> wahsaga schrieb zu vergleichbarem mal:
"
Forenposting mit Performancefrage Bewertungsfaustregel:
Wer Fragen nach der Performance solcher Kinkerlitzchen stellt, der 
programmiert vermutlich noch nicht mal ansatzweise performant. 
Andernfalls, wenn er wirklich und zu Recht an einer Applikation arbeiten 
würde, bei der dieses Quentchen entscheidend ist, sollte er diese Frage 
gar nicht mehr stellen müssen.
"
Moderator Persönliche Seite #4692090
Lesenswert?

Peter II schrieb:
> Damit es schneller ist, muss der Divisor aber zu Compilezeit konstant
> sein.

Nein.  Auch zur Laufzeit ist eine Division durch 2^N immer noch
schneller als andere Divisionen.  Der Algorithmus ist dann schneller
fertig.  (Zur Compilezeit kann es nur der Compiler gleich optimieren.)

Da geht's den Computern wie den Menschen.  Ins Dezimalsystem
übertragen: wenn du 37568 durch 100 dividieren sollst, bist du mit
dem Ergebnis auch viel schneller fertig, als wenn du es durch 101
teilen sollst.
Gast #4692109
Lesenswert?

Mark B. schrieb:

> Zuerst einmal will man in aller Regel korrekte Ergebnisse haben.

Ja, absolut korrekte Ergebnisse und die dann noch instantan berechnet, 
das ist natürlich das Ideal.

Das Blöde ist halt nur: das geht nicht zu machen. Es wird immer eine 
gewisse Laufzeit erforderlich sein und oft werden auch gewisse 
Abweichungen vom absolut korrekten Ergebnis auftreten müssen.

Der Trick in der Numerik ist, einen geeigneten Kompromiss zwischen 
Korrektheit und Laufzeit zu finden. Blöderweise ist aber wiederum von 
der Anwendung abhängig, welcher Kompromiss geeignet ist.

Wer das nicht begriffen hat, hat vom Programmieren noch nicht viel 
verstanden.
Gast #4692123
Lesenswert?

c-hater schrieb:
> Ja, absolut korrekte Ergebnisse und die dann noch instantan berechnet,
> das ist natürlich das Ideal.

Ohne Laufzeit geht nur die wegoptimierte Division durch 1, aber warum 
sollte man da überhaupt dividieren, wenn es vorher bekannt ist. Alles 
andere hat was von Radio Eriwan...
Gast #4692148
Lesenswert?

Das Schieben ist schneller ABER eben nur zur entsprechenden Basis des 
Zahlensystemes. Bezogen auf binär heißt es du kannst nur durch 2 teilen 
auf die 10erBasis ist es eben nur /10. Somit ist die Aufgabe von dir die 
Dvision so abzubilden das du nicht nur durch die Basis des 
entsprechenden Zahlensystemes dividieren kannst sondern auch andere 
Teiler möglich sind. Dazu brauchst all den anderen Kram....
Gast #4692161
Lesenswert?

Also wenn rechnen müsste:
1
uint8_t Wert = 20 / 5;

Dann mach ich doch gleich so:
1
uint8_t Wert = 4;


;-)

Ansonsten sehe ich das wie

Arduino F. schrieb:
>> wahsaga schrieb zu vergleichbarem mal:
> "
> Forenposting mit Performancefrage Bewertungsfaustregel:
> Wer Fragen nach der Performance solcher Kinkerlitzchen stellt, der
> programmiert vermutlich noch nicht mal ansatzweise performant.
> Andernfalls, wenn er wirklich und zu Recht an einer Applikation arbeiten
> würde, bei der dieses Quentchen entscheidend ist, sollte er diese Frage
> gar nicht mehr stellen müssen.
> "
#4692191
Lesenswert?

Bernd K. schrieb:
> Mark B. schrieb:
>> Entscheidend ist, was der Compiler aus Deinem Code macht. Sehr
>> wahrscheinlich wird er es so umsetzen, dass es keinen Vorteil bringt im
>> Code einen Shift-Befehl hinzuschreiben anstatt einer Division.
>
> Sag das mal dem Keil C51 Compiler.

Okay, also: Ein vernünftiger Compiler wird es so umsetzen, dass es 
keinen Vorteil bringt einen Shift-Befehl hinzuschreiben anstatt einer 
Division. ;-)
Moderator Persönliche Seite #4692490
Lesenswert?

Joachim B. schrieb:
> das dürfte schon der Präprozessor machen und 4 einsetzen vermute ich
> mal.

Präprozessor, Subst.:

Mystischer Teil eines C-Compilers, dessen Möglichkeiten weithin
gefühlsmäßig dramatisch überschätzt werden.  Der P. erledigt einfache
Textersetzungen, bevor der Quelltext einer Übersetzungseinheit zum
eigentlichen Compiler weitergereicht wird.
Moderator Persönliche Seite #4692556
Lesenswert?

Spannungsteiler schrieb:
> --->
> http://www.matuschek.net/avr-codeoptimierung2/

Mikrooptimierung.

Solche Hacks wird man sich nur antun, wenn's auf die paar Takte
wirklich ankommt.  Portiert man den ganzen Salat mal irgendwann
auf einen anderen Prozessor, dann kann einem solcherart
Optimierung ganz schnell auf die Füße fallen, weil sie sich dort
dann plötzlich als Pessimierung entpuppt, ganz davon abgesehen,
dass sie eine bestimmte Byteorder benötigt.

Bei ARM und GCC hat man übrigens Glück: der erkennt, dass all die
vielen Umständlichkeiten von "version2" letztlich zum gleichen
Code führen wie "version1", und schreibt in beiden Fällen den
passenden LSRS-Befehl (mit 22 Bit Schiebeweite) hin. ;-)
#4692739
Lesenswert?

Jörg W. schrieb:
> Joachim B. schrieb:
>> das dürfte schon der Präprozessor machen und 4 einsetzen vermute ich
>> mal.
>
> Präprozessor, Subst.:
>
> Mystischer Teil eines C-Compilers, dessen Möglichkeiten weithin
> gefühlsmäßig dramatisch überschätzt werden.  Der P. erledigt einfache
> Textersetzungen, bevor der Quelltext einer Übersetzungseinheit zum
> eigentlichen Compiler weitergereicht wird.

Er kann aber rechnen, muss es sgoar, und zwar wenn es berechenbare Terme 
in #if Statements gibt.
#4692761
Lesenswert?

Mark B. schrieb:
> Okay, also: Ein vernünftiger Compiler wird es so umsetzen, dass es
> keinen Vorteil bringt einen Shift-Befehl hinzuschreiben anstatt einer
> Division. ;-)

Wobei zu beachten wäre, dass
  int i = a;
  i %= 8;
und
  i >>= 3;
nicht äquivalent sind, weil auch bei Verwendung eines Schiebebefehls mit 
Vorzeichen bei negativen Werten unterschiedlich gerundet wird. Eine 
Divisionoperation, die durch Shift ersetzt wird, kann also komplizierter 
ausfallen als ein Shift allein. Und bei Optimierung auf Grösse kann die 
Division dann u.U. sparsamer ausfallen als dieser Ersatz.
Gast #4692782
Lesenswert?

Es gab auf dem µCNet vor ein paar Jahren einen Thread mit einer 
schnellen Division, die in USA patentiert war. Der Thread stand 
vermutlich im Zusammenhang mit der Emulation des DIV-Befehls eines 8051 
auf einem AVR-Controller. Vielleicht weiß noch jemand welcher Thread das 
war.
#4693049
Lesenswert?

Jörg W. schrieb:
> Der P. erledigt einfache
> Textersetzungen,
Cyblord -. schrieb:
> Er kann aber rechnen, muss es sgoar, und zwar wenn es berechenbare Terme
> in #if Statements gibt.
Cyblord -. schrieb:
> Dein Beitrag suggeriert er mache ausschließlich
> einfache Textersetzungen. Was rechnen dann doch ausschließt.

danke, wusste ich doch das der Prä rechnen kann, aber irgendeiner muss 
ja immer widersprechen!

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