Wie schnell is Cosinus und Sinus?
Übersicht

LukasBetreff: Wie schnell is Cosinus und Sinus? |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Mit welchem Befehl(von der Schnelligkeit) kann man Cosinus oder Sinus vergleichen?
Ist es sehr lastig wenn man ungefähr 50 Cosinus Rechnungen pro Schleifendurchgang hat? mfg |
||
![]() |
Mr.Keks |
![]() Antworten mit Zitat ![]() |
---|---|---|
50 sind kein problem...
abgesehen davon kannst du ja auch in arrays m stile von Dim sinus#(360) zwischenspeichern, wenn du keine zu hohe winkelgenauigkeit brauchst ^^. |
||
MrKeks.net |
Lukas |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Hey, danke das ist ne gute Idee.
Darauf bin ich gar nicht gekommen. mfg |
||
![]() |
StepTiger |
![]() Antworten mit Zitat ![]() |
---|---|---|
theorethisch kannst du das auch so machen:
da sich die mathemathischen kurven sinus und cosinus genau negativ gegenüberstehen und um pi/4 zueinander verschoben sind ergibt sich: cos(x)=-sin(x+90) umgeformt: cos(x)=sin(x-90) anders herum das selbe: sin(x)=-cos(x-90) umgeformt dann natürlich sin(x)=cos(x+90) also schlussfolgert sich cosinus aus sinus (wohl der grund warum es co-sinus heißt ![]() |
||
Noch gestern standen wir am Abgrund, doch heute sind wir schon einen Schritt weiter.
Computer: AMD Sempron 3000+; ATI Radeon 9800 Pro; 512 MB DDR RAM 400Mhz; Asus E7N8X-E Deluxe; Samsung 200GB HD 5.4ns acces t Gewinner: BP Code Compo #2 Π=3.141592653589793238...<--- und das aus dem kopf ![]() Seit der Earthlings-Diskussion überzeugter Fleisch(fr)esser. |
![]() |
Jan_Ehemaliger Admin |
![]() Antworten mit Zitat ![]() |
---|---|---|
ich würde bei der Berechnung noch mod 360 machen. | ||
between angels and insects |
trooper |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
lookup tables sind nicht wesentlich schneller als die einfachen sin/cos aufrufe, einige behaupten sogar, dass den wert vom speicher zu holen langsamer ist, als die berechnung von sin/cos auf modernen systemen
-> lookup tables lohnen sich nicht |
||
-- imtane.de.vu --
a cherring ping |
![]() |
Mr.Keks |
![]() Antworten mit Zitat ![]() |
---|---|---|
@trooper: quelle? vielleicht ist mein system ja nicht modern genug, aber bei mir macht das durchaus einen geschwindigkeitsunterschied bei vielen sinus/cosinus! | ||
MrKeks.net |
Skulk |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Das liese sich ja anhand eines sehr simplen Benchmarking-Programmes überprüfen.
Code: [AUSKLAPPEN] Const ITERATIONEN_PRO_BEFEHL = 300000
Dim lookup%(360) Graphics 800,600,32,2 Print "Starte Berechnung über Sin() und Cos()" started%=MilliSecs() For i = 1 To ITERATIONEN_PRO_BEFEHL temp% = Sin(i Mod 360) Next stopped%=MilliSecs() diff% = stopped - started Print "Sin() wurde " + ITERATIONEN_PRO_BEFEHL + " ausgeführt. Dauer: " + diff + " ms" Print "Bereite LookUpTable vor" For i= 0 To 359 lookup(i) = Sin(i) Next Print "Starte Berechnung über Lookup()" started%=MilliSecs() For i = 1 To ITERATIONEN_PRO_BEFEHL temp% = lookup(i Mod 360) Next stopped%=MilliSecs() diff% = stopped - started Print "Sin() wurde " + ITERATIONEN_PRO_BEFEHL + " ausgeführt. Dauer: " + diff + " ms" das ergibt bei mir eine differenz von 30ms : 5ms klar ein richtiges benchmarking würde den test mehrfach ausführen und die durchschnittsergebnisse bilden. aber das verhältnis sollte erkennbar sein. und KEINE Zweifel dulden ![]() |
||
War doesn't determine who's right,
war determines who's left... |
![]() |
Der Wanderer |
![]() Antworten mit Zitat ![]() |
---|---|---|
@Trooper
Das kommt darauf an, wie (und wie genau) Sin/Cos berechnet wird und wie die Timings des Systems sind. Tendentiell sollte aber ein Sin/Cos als Lookuptable schneller sein, auch wenn das vielleicht ab und zu nicht ganz zu trifft. Mit einem LUT ist man jedoch auf der sicheren Seite was die Speed angeht. Ich würde aber für Sin und Cos zwei Tables anlegen, oder einen Table mit zwei versetzen Pointern, denn das "Winkel+90" macht wieder ein wenig Speed zunichte, und darum gehts ja bei dem Lookuptable. Sonst könnte man ja auch noch die Punkt-Symmetrie von Sinus ausnutzen, bräuchte also nur Werte von 0 bis pi/2, wenn der Table unbedingt klein sein muss. Des weiteren würde ich eine Scala von Zweierpotenzen für den LUT wählen, und statt MOD (erfordert eine Division!) ein bitweises AND nehmen, also etwa sowas wie sinus = sinTable(alpha AND $2FF) Wenn der Table 1024 einträge hat. Und für den Winkel alpha würde ich integer nehmen, kein Float, das spart die Umwandlung von alpha. Man kann ja sowieso nur Winkel berechnen in der Stufigkeit des LUT. |
||
![]() |
Rone |
![]() Antworten mit Zitat ![]() |
---|---|---|
Natürlich sind Tables viel schneller...
Bei mir sind sogar Sie sogar ca. 15 mal schneller als die sin/cos Funktionen... Code: [AUSKLAPPEN] Dim Sinus(360) For i=0 To 359 Sinus(i) = Sin(i) Next timer =MilliSecs() For k=0 To 100000 For i=0 To 360 wert=Sin(i) Next Next timer=MilliSecs()-timer timer2=MilliSecs() For k=0 To 100000 For i=0 To 360 wert=Sinus(i) Next Next timer2=MilliSecs() -timer2 Print "Funktion: "+timer Print "Table: "+timer2 WaitKey End mfg Edit: Ops, da war ich wohl zu langsam... |
||
![]() |
StepTiger |
![]() Antworten mit Zitat ![]() |
---|---|---|
Der Wanderer hat Folgendes geschrieben: ... Ich würde aber für Sin und Cos zwei Tables anlegen, oder einen Table mit zwei versetzen Pointern, denn das "Winkel+90" macht wieder ein wenig Speed zunichte, und darum gehts ja bei dem Lookuptable...
Stimmt nicht! Das zweimalige zurückgreifen auf den Speicher nimmt speed, da der benötigte Speicher ja für die Tabellen benötigt wird! Beweis: Code: [AUSKLAPPEN] Const ITERATIONEN_PRO_BEFEHL = 3000000
multiply#=1000 Dim lookup%(360*multiply#) Dim lookup2%(360*multiply#) Graphics 800,600,32,2 Print "Starte Berechnung über Sin() und Cos()" started%=MilliSecs() For i = 1 To ITERATIONEN_PRO_BEFEHL temp% = Sin(i/multiply# Mod 360.) temp% = Cos(i/multiply# Mod 360.) Next stopped%=MilliSecs() diff% = stopped - started Print "Sin() wurde " + ITERATIONEN_PRO_BEFEHL + " ausgeführt. Dauer: " + diff + " ms" WaitKey Print "Bereite LookUpTable vor" For i= 0 To 360*multiply# lookup(i) = Sin(i/multiply#) lookup2(i) = Cos(i/multiply#) Next Print "Starte Berechnung über Lookup()" started%=MilliSecs() For i = 1 To ITERATIONEN_PRO_BEFEHL temp% = lookup(i/multiply# Mod 360) temp% = lookup(i/multiply#+90 Mod 360) Next stopped%=MilliSecs() diff% = stopped - started Print "Sin() wurde " + ITERATIONEN_PRO_BEFEHL + " ausgeführt. Dauer: " + diff + " ms" WaitKey started%=MilliSecs() For i = 1 To ITERATIONEN_PRO_BEFEHL temp% = lookup(i/multiply# Mod 360) temp% = lookup2(i/multiply# Mod 360) Next stopped%=MilliSecs() diff% = stopped - started Print "Sin() wurde " + ITERATIONEN_PRO_BEFEHL + " ausgeführt. Dauer: " + diff + " ms" WaitKey Code 1 ist mit sin und cos Code 2 ist mit sin und cos aus der selben LUT Code 3 ist mit sin und cos aus extra LUT Code 2 ist am schnellsten! weiter: Rone hat Folgendes geschrieben: Natürlich sind Tables viel schneller...
Bei mir sind sogar Sie sogar ca. 15 mal schneller als die sin/cos Funktionen... Code: [AUSKLAPPEN] Dim Sinus(360) For i=0 To 359 Sinus(i) = Sin(i) Next timer =MilliSecs() For k=0 To 100000 For i=0 To 360 wert=Sin(i) Next Next timer=MilliSecs()-timer timer2=MilliSecs() For k=0 To 100000 For i=0 To 360 wert=Sinus(i) Next Next timer2=MilliSecs() -timer2 Print "Funktion: "+timer Print "Table: "+timer2 WaitKey End mfg Edit: Ops, da war ich wohl zu langsam... nur, wenn nur der sinus ganzer zahlen benötigt wird. Erweitert man den array auf etwa ein hundertstel pro zahl, so ist es kaum schneller mit table. Beweis: Code: [AUSKLAPPEN] mult#=100
Dim Sinus(360*mult#) For i=0 To 360*mult# Sinus(i) = Sin(i/mult#) Next timer =MilliSecs() For k=0 To 1000 For i=0 To 360 * mult# wert=Sin(i/mult#) Next Next timer=MilliSecs()-timer timer2=MilliSecs() For k=0 To 1000 For i=0 To 360 * mult# wert=Sinus(i/mult#) Next Next timer2=MilliSecs() -timer2 Print "Funktion: "+timer Print "Table: "+timer2 WaitKey End desweiteren hat es den nachteil, dass die LUT den gesamten speicher wegfressen. Versucht man vier komma stellen zu immitieren, so sind etwa 100 megabyte flöten ALSO MERKEN: Werden keine genauen Werte benötigt, LUT Werden genaue Werte benötigt, auf jeden Fall sin und sin(blabla+90) Die Resourcen werden für Bilder und anderen Kram benötigt! Keine großen Arrays!!! |
||
Noch gestern standen wir am Abgrund, doch heute sind wir schon einen Schritt weiter.
Computer: AMD Sempron 3000+; ATI Radeon 9800 Pro; 512 MB DDR RAM 400Mhz; Asus E7N8X-E Deluxe; Samsung 200GB HD 5.4ns acces t Gewinner: BP Code Compo #2 Π=3.141592653589793238...<--- und das aus dem kopf ![]() Seit der Earthlings-Diskussion überzeugter Fleisch(fr)esser. |
![]() |
Der Wanderer |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ja, gemeinsamen Speicher für Sin/Cos verwenden bringt mehr Lokalität rein und es wird wahrscheinlicher einen Cache-Hit zu bekommen, in sofern ist das schneller.
Ich kenne BlitzBasic auf dem PC nicht, ich dachte deshalb es könnte langsamer sein. In C oder ASM (oder Amiblitz) wäre die "+ 90 Grad" natürlich schneller. Allerdings sind die ganzen Beispiele fehlerhaft, weil 1. der Sin LUT linear ausgelesen wird, was in natürlich enorm beschleunigt. Die echte Sin Funktion kann das nicht ausnutzen. 2. Die Temp Variable nicht weiter verwendet wird. Möglicherweise wird die ganze Zeile wegoptimiert. Es liegt doch glaube ich ein GCC drunter, oder? Der würde das machen. Wenn man den Sinus genau braucht, sollte man ihn auch mit Sinus berechnen, das stimmt schon. Aber sehr oft braucht man das nicht so genau, da kann man mit einem kleinen LUT arbeiten. Bei 1 Grad Auflösung wären das 360*4 bytes, das bringt keinen um. Also nicht falsch verstehen, der Sinus ist natürlich genau berechnet im LUT, nur kann man nicht jeden Wert hineingeben. Für Spiele, z.B. ein Raumschiff was sich um die eigene Achse dreht reicht ein LUT meistens völlig aus. |
||
![]() |
stfighter01 |
![]() Antworten mit Zitat ![]() |
---|---|---|
und wenn der table 1 MB wäre, wen würde das kratzen?
dann hast du die genauigkeit auf 0,0014 grad und die geschwindigkeit wäre optimal. |
||
Denken hilft! |
![]() |
StepTiger |
![]() Antworten mit Zitat ![]() |
---|---|---|
aber nur, wenn der speicher keinen namen hätte und nie aufgerufen werden würde. Und dann auch nur wenn sich die werte unter 65536 halten, wenn es integer sind oder wenn sie sich unter 2^-15 halten. Und dann auch nur, wenn man nicht einrechnet, dass bb keine begrenzungen für zahlen hat, die man nach optimum einstellen kann
sonst verbraucht ein array an die 1 MB wenn etwa 1000 werte gespeichert werden sollen. Will man es noch genauer (als 0.36°) so benötigt man noch mehr speicher und bei 100.000 Werten (eine Genauigkeit von 0.0036!) hat man dann schon seine 100MB voll. Und so eine Genauigkeit braucht man in großen Dimensionen! Da will man keine gerundeten werte! (gibt sonst einen Stottereffekt, z.B. bei großen Zahnrädern in einem Horrorgame oder einem Uhrwerk als Nachbau des Big Ben oder was auch immer) |
||
Noch gestern standen wir am Abgrund, doch heute sind wir schon einen Schritt weiter.
Computer: AMD Sempron 3000+; ATI Radeon 9800 Pro; 512 MB DDR RAM 400Mhz; Asus E7N8X-E Deluxe; Samsung 200GB HD 5.4ns acces t Gewinner: BP Code Compo #2 Π=3.141592653589793238...<--- und das aus dem kopf ![]() Seit der Earthlings-Diskussion überzeugter Fleisch(fr)esser. |
![]() |
Der Wanderer |
![]() Antworten mit Zitat ![]() |
---|---|---|
@StepTiger
Deine Rechnung ist für mich nicht nachvollziehbar. Denkst du eine Zahl verbraucht 1kb !? Wenn es in Floats gespeichert wird, verbrauchen 100.000 Zahlenwerte 400kb. Ob da nun drauf zugegriffen wird oder nicht spielt doch keine Rolle. Und wie schon erwähnt, sind die Werte des LUT ja nicht gerundet sondern exakt wie der Float Wert den du berechnen würdest. Nur der Definitionsbereich wird eingeschränkt. Wenn sich deine Zahnräder also in jedem Schritt 1 Grad weiter bewegen, und du einen LUT mit 360 Einträgen hast, verlierst du überhaupt keine Genauigkeit. Oft weis man ja soweiso, welche Winkel hineingehen werden, z.B. wenn man eine FFT berechnet. Da kann man in aller Ruhe die Werte vorherberechnen. Aber wie gesagt, es gibt sicher auch Anwendungen wo ein LUT nicht sinnvoll ist. |
||
![]() |
stfighter01 |
![]() Antworten mit Zitat ![]() |
---|---|---|
@Step tiger
types sollte man für so sachen nicht verwenden, das könnte den speicherverauch in der tat ein wenig erhöhen ![]() @all ok,ok,ok vergesst alles was hier gesagt wurde schnell wieder. ich hab mal nen code für eine lut geschrieben (siehe code-sektion ) allerdings ist das nachsehen in der tabelle doppelt so langsam wie der aufruf von cos. scheint als wären funktionsaufrufe in blitz elends langsam 8) auf meinem system benötigt der cos befehl für 1000000 berechnungen 198 ms und mit meiner funktion 400. wenn ich die berechnung aus der funktion rausnehme, dauerts auch so um die 190 ms. und die moral von der geschicht, speicher keinen sinus nicht. ( wer will kann gern noch meinen code optimiere, aber ich denke da ist nicht mehr viel rauszukitzeln ) mfg stf |
||
Denken hilft! |
![]() |
Der Wanderer |
![]() Antworten mit Zitat ![]() |
---|---|---|
Aus dem LUT musst du natürlich direkt auslesen. Ein Funktionsaufruf ist immer langsam, das ist klar. (Register und Rücksprungadresse retten, Parameter laden etc.)
Du solltest auch nicht von deiner Config auf andere schliessen. Die Geschwindigkeitverhältnisse können sich schon verändern. Vielleicht ist aber auch der Overhead von BB zu gross, und macht den Vorteil des LUT wieder kaputt. In AB2 oder ASM wäre ein LUT sicher schneller. |
||
![]() |
stfighter01 |
![]() Antworten mit Zitat ![]() |
---|---|---|
@wanderer
ich muss dir schon beipflichten, aber nach meinen tests gestern glaub ich nicht das ein lut in bb wirklich sinnvoll ist. vielleicht unter c++ wo funktionsaufrufe nicht so viel overhead mit sich führen und die arrayszugriffe wesentlich direkter vonstatten gehen, aber unter bb würde ich es nicht mehr nutzen. und selbst mit direktem auslesen bin ich gerade mal genauso schnell wie die nativen sin/cos berechnungen (abgesehen davon ist es unakzeptabel das ganze NICHT in eine funktion zu packen ). |
||
Denken hilft! |
![]() |
Der Wanderer |
![]() Antworten mit Zitat ![]() |
---|---|---|
Wieso sollte man das in eine Funktion packen ?
Ein Array Aufruf sieht doch fast genauso aus, und hat auch sonst keine Nachteile. (ausser, dass man das MOD 360 immer machen muss). Sinnvoller wäre, es in ein Macro zu packen. Beim Macro entfällt ja das Springen und Retten der Daten und Laden der Parameter. Kann man in BB für den PC eigentlich auch inline ASM coden ? |
||
![]() |
stfighter01 |
![]() Antworten mit Zitat ![]() |
---|---|---|
der aufruf gestaltet sich schon etwas komplizierter
wenn dein array nicht gerade 360 werte gespeichert hat musst du den arrayindex auch noch berechnen und alternativ für den cos + 90° um die sinustabelle benutzen zu können. damit wird es schon wieder etwas umständlicher das ganze jedesmal zu schreiben. und ich glaube nicht das man mit den standard bb werkzeugen vernünftig makros einbauen kann. zudem hat es auf meinem system ( 3200 amd ) keinen signifikanten leistungsvorteil gebracht, und auf noch schnelleren systemen wird ein speicherzugriff wohl noch mehr hinterherhinken fürchte ich. damit betrachte ich dieses thema jetzt aber für erledigt. |
||
Denken hilft! |
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group