Archiv verlassen und diese Seite im Standarddesign anzeigen : Geschwindigkeit Division AVR/BASCOM
boeseTURBO-CT
27.07.2007, 12:17
Moin moin,
mal ne Frage (vielleicht hats ja mal jemand gemessen). Wie lange braucht
ein AVR mit 16 MHz um zB. eine byte-Variable durch 18 zu teilen? wieviele Takte nimmt das ungefähr in Anspruch? Wie sieht es mit Multiplikationen aus (die AVR'S haben ja einen Hardware-Multiplicator wird der von BASCOM automatisch angesprochen?)... Addition und Substraktion bei 8 Bit Variablen sollten in einem Takt schaffbar sein oder?
VIele Grüsse
Jan
Lunarman
27.07.2007, 12:20
Einen Takt? Kommt drauf an, womit du proggst. In Assembler legst du es einfach selbst fest, in C so ungefähr, und in BAscom weiß man nie, kann auch sein, dass die erst + 234 rechnen und das danach wieder richtig abziehen. nee Scherz, aber in BAscom kann ichs dir nicht sagen.
Hallo boeseTURBO-CT,
ja, zwei 8bit-Variablen werden in einem Takt addiert/substrahiert. Beachte aber, dann man die Variablen erst aus dem SRAM laden muss, um sie addieren zu können. Wenn man es auf dem kürzesten Weg macht, würde es 7 Takte brauchen, bis zwei Variablen geladen, addiert und das Ergebnis wieder gespeichert ist. Ob BASCOM diesen Weg auch geht kann ich Dir nicht sagen.
MfG Mark
boeseTURBO-CT
27.07.2007, 13:16
dass ist ja doof ;) gcc kann das direkt :(... Weiß jemand noch genaueres wie "hart" es bei division wird?
Für sowas gibts nen Simulator der Dir genau sagt wie lang was dauert.
Dim A As Byte
Dim B As Byte
A = 245
B = 18
A = A / B
End
"A = A / B" dauert exakt 111 Takte!
MfG
boeseTURBO-CT
27.07.2007, 14:03
ah alles klar. Wusste nicht, dass der Simulator genau so "schnell" ist wie der uc später auch :)
MeckPommER
27.07.2007, 14:08
allein das a=a/b dauert 111 takte, nicht das ganze programm?
boeseTURBO-CT
27.07.2007, 14:14
demnach brauch bascom für eine addition 9 Takte! für eine multiplikation 10 Takte (zb. 6 x 25)
Lunarman
27.07.2007, 14:17
Häh? Warum? Blick ich nich? HAst du das auch simuliert?
allein das a=a/b dauert 111 takte, nicht das ganze programm?
Ja, die eine Programmzeile dauert 111 Takte. :-b
Dass es durch zb 16 schneller geht ist klar, oder?
Dass es durch zb 16 schneller geht ist klar, oder?
Nö, wie kommst Du da drauf. Das man mit Bitschieben schneller sein könnte ist klar, aber Bascom nimmt wohl immer den selben Rechenalgorithmus also dauert ein / 16 auch 111 Takte!
Nein, das wird wahrscheinlich nicht 111 Takte dauern sondern etwas weniger, weil in 16 ein bit weniger 1 ist als in 18.
MfG Mark
EDIT-------------------
Doch nicht. BASCOM rechnet anscheinend anders als ich es vermutet habe.
Nein, das wird wahrscheinlich nicht 111 Takte dauern sondern etwas weniger, weil in 16 ein bit weniger 1 ist als in 18.
MfG Mark
Selbst ein / 2 (was in Assembler ein Takt is \:D/ ) dauert 111 Takte! Wenn Du es nicht glaubst versuche es selber.
boeseTURBO-CT
27.07.2007, 15:03
yo, dass ist doch scheisse wenn man sachen programmieren will, die fix gehen müssen ;) schade dasses keine AVR's mit 40 MHz gibt ;D
Also dass Bascom derart ineffizient ist, war mir neu.
Ein weiterer Grund es nicht zu verwenden, was ich ja auch nicht tue. Aber man kann halt nicht alles haben...
Gruß
Bascom ist ineffizient, da immer vom Ram gelesen wird und nicht mit Registern gearbeitet wird. Ich fand den Codevergleich Artikel im Wiki sehr interessant. Sollte man sich mal anschauen.
https://www.roboternetz.de/wissen/index.php/Codevergleich_AVR-Compiler
Anmerkung: Gcc4 ist nochmals 2 Stufen effizenter.
Dim A As Byte
Dim B As Byte
A = 245
B = 18
A = A / B
End
111 Takte ?
Jeder Kompiler sollte erkennen, daß es sich um konstante Werte handelt und alles zu Kompilierzeit berechnen, wenn man z.B. A an ein Port übergeben möchte, müsste das ganze 1 Takt dauern.
Kein Wunder, daß die Bascomer Megas32 mit 16 MHz brauchen und sich sogar 40 MHz wünschen ;-)
Jeder Kompiler sollte erkennen, daß es sich um konstante Werte handelt und alles zu Kompilierzeit berechnen, wenn man z.B. A an ein Port übergeben möchte, müsste das ganze 1 Takt dauern.
Kein Wunder, daß die Bascomer Megas32 mit 16 MHz brauchen und sich sogar 40 MHz wünschen ;-)
Wenn Bascom richtig schlau wäre wurde es eine leeren Code erzeugen da das Programm ne Berechnung macht die nie verwendet wird :-&
P.S. Bei A = 4 / 2 dauerts nur 3 Takte also ist der Kompiler nicht ganz dumm!
Wenn Bascom richtig schlau wäre wurde es eine leeren Code erzeugen da das Programm ne Berechnung macht die nie verwendet wird
Deswegen hab ich ja das Beispiel mit Portausgabe gemacht
A = 4 / 2 dauerts nur 3 Takte also ist der Kompiler nicht ganz dumm!
Hmm, Register mit 4 laden -> 1 Takt
Shift nach rechts -> 1 Takt
Register in SRAM Speichern -> 2 Takte
:-k
P.S.
Ich weiß schon, der ist wirklich schlau ! 4/2 macht der wahrscheinlich doch zu kompilierzeit also
Register mit 2 laden -> 1 Takt
Register in SRAM Speichern -> 2 Takte
Also ganz klever der Kerl !!!
boeseTURBO-CT
29.07.2007, 23:56
dann muss ich wohl doch auf C++ umsatteln.... Gibs da anständige Oberflächen mit Simulator usw? Oder einfach dann das AVR-Studio benutzen?
Viele Grüsse
Jan
Hallo Jan,
Du kannst das AVR-Studio nur dann benutzen, wenn Du schon WinAVR installiert hast, das es dessen Compiler (AVR-GCC) braucht. AVR-Studio kann aber kein C++ sondern nur C. C++ geht nur mit WinAVR, was aber auch ziemlich gut ist und ausser der Tatsache, dass man die Makefiles selbst erstellen muss, keine anderen Nachteile hat.
MfG Mark
boeseTURBO-CT
30.07.2007, 11:06
Moin moin,
rechnen die C-Varianten denn direkt in den Registern? Oder auch erst aus dem SRAM holen und wieder reinschreiben?
AVR rechnet nur im Register
Hallo Jan,
wie Vitis bereits gesagt hat, rechnen AVRs nur in Registern. Was bei C-Compilern aber bei eingeschalteter Optimierung anders ist, ist dass sie versuchen, die Werte auch in den Registern zu halten, wenn sie nochmals verwendet werden. Z.B: wenn man sowas hier hat:
a=b+c;
d=b;
c=d+a;
macht BASCOM ungefähr folgendes:
//erste zeile
lds r16,adresse von b //lade r16 mit dem inhalt von b
lds r17,adresse von c //lade r17 mit dem inhalt von c
add r16,r17 //addiere r16 und r17, und speichere das erg. in r16
sts adresse von a,r16 //speichere den inhalt von r16 in a
//zweite zeile
lds r16,adresse von b //lade r16 mit dem inhalt von b
sts adresse von d,r16 //speichere r16 in d
//dritte zeile
lds r16,adresse von d //lade r16 mit dem inhalt von d
lds r17,adresse von a //lade r17 mit dem inhalt von a
add r16,r17 //addiere r16 und r17, und speichere das erg. in r16
sts adresse von c,r16 //speichere den inhalt von r16 in c
ein guter C-Compiler wie avr-gcc macht aber etwas viel kürzeres:
//erste zeile
lds r16,adresse von b //lade r16 mit dem inhalt von b
lds r17,adresse von c //lade r17 mit dem inhalt von c
add r17,r16 //r17=r16+r17
sts adresse von a,r17 //speichre r17 in a
//zweite zeile
sts adresse von d,r16 //speichere r16 in d, da in r16 immer ncoh der inhalt von b ist
//dritte zeile
add r16,r17 //r16=r16+r17 //da in r17 immer noch a ist und d=b ist
sts adresse von c,r16 //c=r16
So wären es mit BASCOM gut 10 Befehle (wahrscheinlich sogar noch mehr), mit avr-gcc mit eingeschaltetem Optimierer aber nur 7. Dementsprechend kann der erzeugte Code beim avr-gcc durchschnittlich gut 1,5-2 mal kleiner sein als in BASCOM und wird auch schneller ausgeführt.
MfG Mark
boeseTURBO-CT
30.07.2007, 13:36
Atmel hätten den AVR's ruhig ein hardware-divider spendieren können :((( Dann wär das alles schonmal fixer... Gibt es ne Möglichkeit in bascom die Division zu beschleunigen?
SprinterSB
30.07.2007, 13:53
Manche Compiler optimieren die Division durch eine Konstanten, wie zB Division durch 3:
A = B / 3
Nehmen wir A und B mal als 8-Bit-Werte, dann ist das (zumindest algebraisch) gleichbedeutend mit.
A = 256 * B / 3 / 256
und nach Rundung von 256/3
A = 85 * B / 256
Die Multiplikation mit 85 wird dabei als 8*8=16 ausgeführt und vom Produkt die obersten 8 Bits als Ergebnis genommen.
Das geht schneller, weil Multiplikation und oberen Teil verwenden weitaus billiger ist als ne Division (zumindest für AVR).
Sowas kann man auch händisch hinschreiben. Allerdings können sich die Ergebnisse von A div 3 und 85*A div 256 wegen der Rundung um 1 unterscheiden.
Hier (für 3) bekommt man Gleichheit so:
A div 3 = 85*(A+1) div 256
boeseTURBO-CT
30.07.2007, 14:37
so, hab angefangen einige Routinen etwas zu optimieren :))... im echten Code ist A natürlich eine errechnete Variable :)...
immerhin habe ich es geschafft, dass der Code 5x schneller läuft....
Dim A As Word
Dim B As Word
Dim C As Word
A= 25000
'Beispiel 1 (braucht 282 Takte):
B=A/10
c=B*15
' Beispiel 2 (braucht 56 Takte):
B = A
Shift A , Right , 1
C = B + A
' Beispiel 3 (braucht 37 Takte):
C = A * 1.5
C ist dann allerdings 50000 nicht 37500...
' Beispiel 4 (656 Takte!!!!)
C = A * 1.5
C ist diesmal ne Single-Variable....
man kann da also doch noch ne Menge optimieren :) In diesem Fall ist die Shift-Methode auf jedenfall die richtige!
Powered by vBulletin® Version 4.2.5 Copyright ©2025 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.