PDA

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.

p_mork
27.07.2007, 13:12
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?

Rofo88
27.07.2007, 14:02
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?

Rofo88
27.07.2007, 14:18
allein das a=a/b dauert 111 takte, nicht das ganze programm?

Ja, die eine Programmzeile dauert 111 Takte. :-b

Gock
27.07.2007, 14:20
Dass es durch zb 16 schneller geht ist klar, oder?

Rofo88
27.07.2007, 14:23
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!

p_mork
27.07.2007, 14:38
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.

Rofo88
27.07.2007, 14:43
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

Gock
27.07.2007, 17:06
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ß

s.o.
27.07.2007, 17:43
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.

izaseba
27.07.2007, 17:49
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 ;-)

Rofo88
27.07.2007, 18:13
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!

izaseba
27.07.2007, 18:27
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

p_mork
30.07.2007, 10:48
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?

Vitis
30.07.2007, 11:30
AVR rechnet nur im Register

p_mork
30.07.2007, 12:03
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!