Werbung
Bei nur 85 Zyklen kann man kaum eine richtige Reihenentwicklung mehr machen. Das kommt mir auch ausgesprochen kurz vor. ZU erwarten wären eigentlich Zeiten etwas langsamer als eine Division.
Kann es sein das das nur für einen Speziellen Wert (z.B. 0) gilt, oder für Integer als Ergebnis ?
Bei dem ersten Beispiel wird der Sinus während des Compilierens ausgerechenet. Wofür dann noch 85 Zyklen gebraucht werden weiss ich nicht. Das Kopieren einer Konstante solle nicht so lange dauern.
Beim 2 ten Beispiel scheint der Compiler das nicht so weit zu optimieren wie im ersten Beispiel. Da wird dann der Sinus wohl wirklich ausgerechent. Die Zeit sieht auch irgendwie realistisch aus für eine Reihentwicklung. Noch etwas langsamer ist meistens log und der Arcus-Tangens.
*lol* Wenn man beide Varianten in EINE source schreibt, ersparte er sich die ganze Rechnerei und nimmt nur Literale.
(müsste man gucken, ob das nur für PI gilt oder für alle werte
jetzt schau ich mir noch an, was er macht, wenn ich ihn zum Rechnen zwingeCode://---------------------------------------- C = Sin(3.1415) //---------------------------------------- LDI XL,0x60 LDI XH,0x00 LDI ZL,0x8C LDI ZH,0x03 CALL L_0x0276 // 4 Byte Literal 0x38C --> C-single //---------------------------------------- C = 3.1415 //---------------------------------------- LDI XL,0x60 LDI XH,0x00 LDI ZL,0x90 LDI ZH,0x03 CALL L_0x0276 // 4 Byte Literal 0x390 --> C-single //---------------------------------------- C = Sin(c) //---------------------------------------- LDI ZL,0x60 LDI ZH,0x00 CALL L_0x036E // C-single --> R13, 14, 15, 16 LDI ZL,0x0D LDI ZH,0x00 LDI XL,0x60 LDI XH,0x00 CALL L_0x0286 // R13, 14, 15, 16 --> C-single //---------------------------------------- CLI // "END" L_0x00B8: RJMP L_0x00B8 Literal-0x038c .DB 0x04, 0x4F, 0xC2, 0x38 Literal-0x0390 .DB 0x56, 0x0E, 0x49, 0x40 ;.O.8V.I@
mfg robert
Wer glaubt zu wissen, muß wissen, er glaubt.
mich würde mal ein arcus sinus interessieren, wie unterschiedlich verhalten sich eigentlich C und Bascom bei solchen sachen ... in C verwende ich die math.h von winavr
mfg robert
Wer glaubt zu wissen, muß wissen, er glaubt.
achso, ich dachte du hast dir nen debugger o.ä. zur brust genommen und einfach gemessen ^^
ich hab atm auch zu viel um die ohren um mir das auszurechnen oder nachzulesen, aber n kollege von mir müsste u.a. mit asin arbeiten und das könnte eventuell zeitkritisch werden, da wollt ich einfach mal nachfragen
Sorry, wenn ich diesen "alten" Thread auspacke. Ich bin auf ihn gestossen, weil ich zur Laufzeitoptimierung meiner DS1820-Temperatur-Auswertung ein paar Anregungen gesucht habe.
Ich möchte anmerken, das Schiebeoperationen als Ersatz für Divisionen durch 2, 4, 8, ... nur für vorzeichenlose, ganzzahlige Variablentypen (Byte, Word, Long) äquivalent sind, da Bascom bei Schiebeoperationen nicht das Vorzeichen berücksichtigt. D.h. Rechtsschieben bei Integervariablen ist nur solange korrekt, wie die Integervariable größer/gleich Null ist.Zitat von mycroc
In folgendem Programmbeispiel habe ich eine Integer-Division durch 2 mit Hilfe des Inline-Assemblers realisiert und mit der Integer-Division selbst, sowie dem einfachen Rechtsschieben verglichen.
Das Programmbeispiel kann direkt im Simulator ausgeführt werden.
MfGCode:Dim X0 As Byte , X1 As Byte Dim X As Integer At X0 Overlay Dim Y As Integer Do '******************************************************************************* '*** Integer Variable eingeben *** '******************************************************************************* Input "x:" , X nop '******************************************************************************* '*** Integer-Division durch 2 *** '******************************************************************************* Y = X / 2 nop Print Y '******************************************************************************* '*** Rechtsschieben Integer Variable *** '******************************************************************************* Y = X Shift Y , Right , 1 Print Y nop '******************************************************************************* '*** Rechtsschieben Integer Variable mit Vorzeichen *** '******************************************************************************* push r24 'R24 retten push r25 'R25 retten lds r24,{x0} 'LSB Integer in R24 lds r25,{x1} 'MSB Integer in R25 sbrc r25,7 'Wenn Integer negativ.. adiw r24,1 '..dann Incrementiere Integer asr r25 'Rechtsschieben MSB ror r24 'Rechtsschieben LSB sts {x0},r24 'R24 in LSB Integer sts {x1},r25 'R25 in MSB Integer pop r25 'R25 wiederherstellen pop r24 'R24 wiederherstellen nop Print X '******************************************************************************* Loop End
screwdriver
edit:
Der Variablentyp LONG hat einen Wertebereich von -2147483648 bis 2147483647 und ist zwar ganzzahlig aber vorzeichenbehaftet. Für Long gilt also das gleiche wie für Integer.
Der im Codefenster vorgestellte Algorithmus ist direkt aus einem meiner Quelltexte kopiert. In etwas abgeänderter Form und als nettes Macro verpackt, ist er jedoch recht gut allgemein anwendbar. Wer möchte kann ja noch eine Zählschleife drumrum tun und kann somit Mehrfach-Shiften.
Laufzeiten:Code:Dim Intvar As Integer 'Integervariable Dim Y As Integer '******************************************************************************* '*** Macro: Asr_Int16 *** '******************************************************************************* '*** Aufruf mit Adresse der zu schiebenden Integervariable im Z-Register *** '******************************************************************************* Macro Asr_int16 ldd r24,z+0 'Lowbyte Integer in R24 ldd r25,z+1 'Highbyte Integer in R25 sbrc r25,7 'Wenn Integer negativ, .. adiw r24,1 '.. dann Intvar inkrementieren asr r25 'Schiebe Highbyte rechts ror r24 'Schiebe Lowbyte rechts std z+0,r24 'R24 in Lowbyte Integer std z+1,r25 'R25 in Highbyte Integer End Macro '******************************************************************************* '*** Hauptprogramm *** '******************************************************************************* Do Input "IntVar: " , Intvar Y = Intvar / 2 Print Y Loadadr Intvar , Z 'Adresse Integervariable in Z-Register laden Asr_int16 'Integervariable Rechtsschieben Print Intvar Loop End
+1000 / 2 : 277 Zyklen, mit Asr_int16 nur 14 Zyklen
-1000 / 2 : 312 Zyklen, mit Asr_int16 nur 15 Zyklen
...Hat jemand vielleicht eine Erklärung dafür?....
Also ich zweifle eure Zeitmessungen sehr stark an, weil ihr euch mit dem ASM-Code von Bascom überhaupt noch nicht geschäftigt habt.
Werte mal die Zyklen vom ASM-Sourse aus, dann werdet ihr staunen, was da für Werte rauskommen. Und diese Werte sind auch die Zeiten, die der Atmega braucht.
Die Zahlen sind schon plasibel. Wenn man das im Simulator durchläuft, nimmt einem der Simulator das zählen der Zyklen schon ab. Da muß man sich den Code auch gar nicht mehr anschauen. Nur wenn man wissen will wieso etwas besonders schnell oder langsam ist ist das nötig. Besonders bei Division und Multiplication kann die Zeit etwas von den Zahlen abhängen.
Die echte Division ist halt recht langsam, daher die rund 300 Zyklen auch für eine Division durch 2. Der extra inline ASM code ist dann entsprechend schneller. Ein guter Compiler hätte das .../2 auch gleich durch den ASM code oben, oder zumindest was ähnliches ersetzt.
Lesezeichen