sin und cos sind langsam, gibt es eine Alternative?

9

Mein Spiel muss sich um einen bestimmten Winkel bewegen. Dazu erhalte ich den Vektor des Winkels über sin und cos. Leider sind Sünde und Kosten mein Engpass. Ich bin mir sicher, dass ich nicht so viel Präzision brauche. Gibt es eine Alternative zu einem C sin & amp; Cos und Look-Up-Tabelle, die anständig ist, aber sehr schnell?

Ich hatte das gefunden:

%Vor%

Leider scheint das nicht zu funktionieren. Ich erhalte ein signifikant anderes Verhalten, wenn ich diese Sünde anstelle von C sin verwende.

Danke

    
jmasterx 23.05.2011, 00:50
quelle

8 Antworten

7

Für Ihre fastSin() sollten Sie in der Dokumentation nachsehen, für welchen Bereich sie gültig ist. Die Einheiten, die du für dein Spiel verwendest, könnten zu groß oder zu klein sein und sie so skalieren, dass sie in den erwarteten Bereich dieser Funktion passen, könnte es besser machen.

BEARBEITEN:

Jemand anders hat erwähnt, dass man ihn in den gewünschten Bereich bringen kann, indem man PI subtrahiert, aber anscheinend gibt es eine Funktion namens fmod um Modulo-Divisionen auf Floats / Doubles zu machen, sollte dies Folgendes tun:

%Vor%

Ich habe keine Ahnung, wie teuer fmod ist, also werde ich als nächstes einen schnellen Benchmark versuchen.

Benchmark-Ergebnisse

Ich habe das mit -O2 kompiliert und das Ergebnis mit dem Programm Unix time ausgeführt:

%Vor%

Das Ergebnis ist, dass sin etwa 1,8 mal langsamer ist (wenn fastSin 5 Sekunden dauert, sin 9). Die Genauigkeit schien auch ziemlich gut zu sein.

Wenn Sie diese Route gewählt haben, stellen Sie sicher, dass Sie die Optimierung mit ( -O2 in gcc) durchführen.

    
Brendan Long 23.05.2011, 00:53
quelle
8

Eine Nachschlagetabelle ist die Standardlösung. Sie könnten auch zwei Nachschlagetabellen für Grad und einen für Zehntelgrade verwenden und sin (A + B) = sin (a) cos (b) + cos (A) sin (b)

verwenden     
rerun 23.05.2011 00:57
quelle
6

Ich weiß, das ist schon ein altes Thema, aber für Leute, die die gleiche Frage haben, hier ist ein Tipp.

Viele Male in 2D- und 3D-Rotation werden alle Vektoren mit einem festen Winkel gedreht. Anstatt die cos() oder sin() für jeden Zyklus der Schleife aufzurufen, erstellen Sie eine Variable vor der Schleife, die bereits den Wert cos(angle) oder sin(angle) enthält. Sie können diese Variable in Ihrer Schleife verwenden. Auf diese Weise muss die Funktion nur einmal aufgerufen werden.

    
JMRC 30.08.2013 19:05
quelle
3

Sie können eine Tabelle S mit 256 Werten berechnen, von sin (0) bis sin (2 * pi). Um dann sin (x) auszuwählen, bringe x in [0, 2 * pi] zurück, kannst du 2 Werte S [a], S [b] aus der Tabelle auswählen, wie etwa & lt; x & lt; b. Daraus ergibt sich eine lineare Interpolation, und Sie sollten eine gute Annäherung haben

  • Speicherspartrick: Sie müssen eigentlich nur aus [0, pi / 2] speichern und Symmetrien von sin (x) verwenden
  • Verbesserungstrick: lineare Interpolation kann ein Problem sein wegen nicht-glatter Ableitungen, Menschenaugen sind gut darin solche Störungen in Animationen und Grafiken zu erkennen. Verwenden Sie dann die kubische Interpolation.
Monkey 23.05.2011 02:25
quelle
3

Wenn Sie die Rückgabe in fastSin als

umformulieren %Vor%

Und schreibe y als (für x & gt; 0)

um %Vor%

Sie können sehen, dass y eine parabolische Näherung erster Ordnung zu sin(x) ist, die so gewählt ist, dass es (0,0), (pi / 2,1) und (pi, 0) durchläuft. Das y*abs(y) ist ein "Korrekturbegriff", der diese Punkte ebenfalls durchläuft.

Diese Form der Approximationsfunktion garantiert, dass die Funktion (1-P) * y + P * y * y auch (0,0), (pi / 2,1) und (pi, 0) durchläuft.

Eine Frage ist "Wie wurde P ausgewählt?". Persönlich würde ich das P wählen, das den geringsten RMS-Fehler über das 0, pi / 2-Intervall erzeugte. (Ich bin mir nicht sicher, ob das P gewählt wurde)

Ссылка

Minimiert dies wrt. P gibt

Ссылка

Dies kann für p

neu definiert und gelöst werden

Ссылка

Nicht sicher, ob dies zu P = 0,225 kommt oder nicht. Wenn nicht, dann ist dieser Wert von P wahrscheinlich eine Verbesserung. (Es sei denn, der andere Wert von P wurde ausgewählt, um eine andere undokumentierte Eigenschaft zu erhalten).

Sie können die Genauigkeit durch Hinzufügen eines zusätzlichen Korrekturterms erhöhen. geben Sie ein Formular so etwas wie return (1-a-b)*y + a y * abs(y) + b y * y * abs(y) . Ich würde a und b by auf die gleiche Weise wie oben finden, wobei diesmal ein System von zwei linearen Gleichungen in a und b zu lösen wäre, anstatt einer einzelnen Gleichung in p . Ich werde die Ableitung nicht als langwierig und die Umwandlung in Latexbilder ist schmerzhaft ...;)

HINWEIS: Bei der Beantwortung einer anderen Frage habe ich an eine andere gültige Wahl für P gedacht. Das Problem ist, dass die Verwendung von Reflektion, um die Kurve in (-pi, 0) zu erweitern, einen Knick in der Kurve bei x = 0 hinterlässt. Ich vermute jedoch, dass wir P so wählen können, dass der Knick glatt wird. Um dies zu tun, nehmen Sie die linken und rechten Ableitungen bei x = 0 und stellen Sie sicher, dass sie gleich sind. Dies ergibt eine Gleichung für P.

    
Michael Anderson 24.05.2011 00:52
quelle
2

Was ist mit

?

x*(0.0174532925199433-8.650935142277599*10^-7*x^2)

für Grad und

x*(1-0.162716259904269*x^2)

für rad on -45, 45 und -pi/4 , pi/4 jeweils?

    
aaa 06.04.2012 22:14
quelle
1

Dies (d. h. die Fastsin-Funktion) approximiert die Sinusfunktion unter Verwendung einer Parabel. Ich vermute, dass es nur für Werte zwischen -π und + π gut ist. Glücklicherweise können Sie 2π addieren oder subtrahieren, bis Sie in diesen Bereich kommen. (Bearbeitet, um anzugeben, was die Sinusfunktion mithilfe einer Parabel approximiert.)

    
James McLeod 23.05.2011 01:06
quelle
1

Sie können diese Approximation verwenden.

Diese Lösung verwendet eine quadratische Kurve:

Ссылка

    
Jefferson Rondan 29.01.2014 15:33
quelle

Tags und Links