Wie schnell is Cosinus und Sinus?

Übersicht BlitzBasic Allgemein

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen

 

Lukas

Betreff: Wie schnell is Cosinus und Sinus?

BeitragDo, Jul 06, 2006 19:04
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDo, Jul 06, 2006 19:10
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDo, Jul 06, 2006 19:17
Antworten mit Zitat
Benutzer-Profile anzeigen
Hey, danke das ist ne gute Idee.

Darauf bin ich gar nicht gekommen.

mfg

StepTiger

BeitragSo, Jul 09, 2006 1:07
Antworten mit Zitat
Benutzer-Profile anzeigen
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 Rolling Eyes )
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 Laughing
Seit der Earthlings-Diskussion überzeugter Fleisch(fr)esser.

Jan_

Ehemaliger Admin

BeitragMo, Jul 10, 2006 8:26
Antworten mit Zitat
Benutzer-Profile anzeigen
ich würde bei der Berechnung noch mod 360 machen.
between angels and insects
 

trooper

BeitragMo, Jul 10, 2006 12:45
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragMo, Jul 10, 2006 13:01
Antworten mit Zitat
Benutzer-Profile anzeigen
@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

BeitragMo, Jul 10, 2006 13:11
Antworten mit Zitat
Benutzer-Profile anzeigen
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

Print "Bereite LookUpTable vor"
For i= 0 To 359
   lookup(i) = Sin(i)
Next

Print
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 Smile
War doesn't determine who's right,
war determines who's left...

Der Wanderer

BeitragMo, Jul 10, 2006 13:20
Antworten mit Zitat
Benutzer-Profile anzeigen
@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

BeitragMo, Jul 10, 2006 13:22
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDi, Jul 11, 2006 21:10
Antworten mit Zitat
Benutzer-Profile anzeigen
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"
Print
WaitKey

Print "Bereite LookUpTable vor"
For i= 0 To 360*multiply#
lookup(i) = Sin(i/multiply#)
lookup2(i) = Cos(i/multiply#)
Next

Print
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 Laughing
Seit der Earthlings-Diskussion überzeugter Fleisch(fr)esser.

Der Wanderer

BeitragDi, Jul 11, 2006 21:51
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDi, Jul 11, 2006 22:37
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragMi, Jul 12, 2006 20:02
Antworten mit Zitat
Benutzer-Profile anzeigen
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 Laughing
Seit der Earthlings-Diskussion überzeugter Fleisch(fr)esser.

Der Wanderer

BeitragDo, Jul 13, 2006 0:18
Antworten mit Zitat
Benutzer-Profile anzeigen
@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

BeitragDo, Jul 13, 2006 1:27
Antworten mit Zitat
Benutzer-Profile anzeigen
@Step tiger
types sollte man für so sachen nicht verwenden, das könnte den speicherverauch in der tat ein wenig erhöhen Wink

@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

BeitragDo, Jul 13, 2006 11:20
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDo, Jul 13, 2006 11:35
Antworten mit Zitat
Benutzer-Profile anzeigen
@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

BeitragDo, Jul 13, 2006 11:41
Antworten mit Zitat
Benutzer-Profile anzeigen
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

BeitragDo, Jul 13, 2006 21:20
Antworten mit Zitat
Benutzer-Profile anzeigen
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!

Gehe zu Seite 1, 2  Weiter

Neue Antwort erstellen


Übersicht BlitzBasic Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group