Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

21

20.02.2006, 21:26

Deine Funktion liefert aber nur für einen begrenzten Wertebereich von x korrekte Ergebnisse, richtig? Wieviel Zeit kostet es denn, mit fmodf x auf den passenden Bereich zu trimmen?

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

22

20.02.2006, 22:03

Ich habe eine mehr oder weniger schockierende Nachricht für Euch ;)

Die Test-Schleife sieht ja z.B. so aus:

C-/C++-Quelltext

1
2
3
    for(int j=0; j<1e4; j++)
        for(float i=0.0f; i<pi; i=i+0.0001f)
            FastSin0(i);


Nun ist es aber so, dass der Compiler den Aufruf von FastSin0 wegoptimiert, d.h. die Messungen waren alle sinnlos, weil die Funktion tatsächlich nie aufgerufen wurde. Ihre Ausführung hat nämlich für den weiteren Programmverlauf keinerlei Bedeutung.

Darum muss man das ändern:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
    float t = 0.0f;

    for(int j=0; j<1e4; j++)
        for(float i=0.0f; i<pi; i=i+0.0001f)
            t += FastSin0(i);

    // GANZ WICHTIG: t ausgeben, weil es sonst auch wegoptimiert wird

    cout << t << endl;


Wenn man das so macht, sind FastSin0 und FastSin1 tatsächlich 4- bzw. 8-mal so schnell wie sinf.

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

23

20.02.2006, 22:14

Das hier ist übrigens noch etwas schneller (jedenfalls bei mir):

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
inline float TnSin(float x)
{
    float f2 = x * x;
    float f3 = x * f2;
    float f5 = f3 * f2;
    float f7 = f5 * f2;
    float f9 = f7 * f2;
    x -= 1.0f / 6.0f * f3;
    x += 1.0f / 120.0f * f5;
    x -= 1.0f / 5040.0f * f7;
    x += 1.0f / 362880.0f * f9;
    return x;
}


Das Vorberechnen von 1/... kann man sich sparen, weil der Compiler das sowieso tut (habe mir den Assembler-Code angesehen).

CW_Kovok

Alter Hase

  • »CW_Kovok« ist der Autor dieses Themas

Beiträge: 836

Wohnort: nähe Bonn

Beruf: Schüler

  • Private Nachricht senden

24

20.02.2006, 22:31

autsch... danke werde es mir morgen nochmal angucken
Was es alles gibt, das ich nich brauche - Aristoteles

DarkFitzi

Alter Hase

Beiträge: 608

Wohnort: Eisenberg, Thüringen

Beruf: Schüler, 10te Klasse

  • Private Nachricht senden

25

20.02.2006, 22:32

interessant was der Compiler so alles für einen macht... :light:
Ich würde die Welt gern verbessern, doch Gott gibt mir den Sourcecode nicht! :-(

rewb0rn

Supermoderator

Beiträge: 2 773

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

26

20.02.2006, 23:22

Nicht genug, dass unsere Arbeitsplätze wegrationalisiert werden, jetzt auch noch unsere Funktionen :rolleyes:

rewb0rn

Supermoderator

Beiträge: 2 773

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

27

20.02.2006, 23:23

Zitat von »"David Scherfgen"«

Deine Funktion liefert aber nur für einen begrenzten Wertebereich von x korrekte Ergebnisse, richtig? Wieviel Zeit kostet es denn, mit fmodf x auf den passenden Bereich zu trimmen?


Welche Funktion?

David Scherfgen

Administrator

Beiträge: 10 382

Wohnort: Hildesheim

Beruf: Wissenschaftlicher Mitarbeiter

  • Private Nachricht senden

28

21.02.2006, 02:35

Alle außer der "echten" Sinusfunktion.
sin(5000*Pi) muss z.B. null ergeben.

Black-Panther

Alter Hase

Beiträge: 1 443

Wohnort: Innsbruck

  • Private Nachricht senden

29

21.02.2006, 13:30

Zitat von »"David Scherfgen"«

Das hier ist übrigens noch etwas schneller (jedenfalls bei mir):

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
inline float TnSin(float x)
{
    float f2 = x * x;
    float f3 = x * f2;
    float f5 = f3 * f2;
    float f7 = f5 * f2;
    float f9 = f7 * f2;
    x -= 1.0f / 6.0f * f3;
    x += 1.0f / 120.0f * f5;
    x -= 1.0f / 5040.0f * f7;
    x += 1.0f / 362880.0f * f9;
    return x;
}


Das Vorberechnen von 1/... kann man sich sparen, weil der Compiler das sowieso tut (habe mir den Assembler-Code angesehen).


Könnte bitte jemand den mathematischen Hintergrund und die Herleitung dieser Sinusberechnung aufzeigen?
stillalive studios
Drone Swarm (32.000 Dronen gleichzeitig steuern!)
facebook, twitter

rewb0rn

Supermoderator

Beiträge: 2 773

Wohnort: Berlin

Beruf: Indie Game Dev

  • Private Nachricht senden

30

21.02.2006, 13:55

Es ist immer noch das Taylorpolynom, hier mit n = 9.
Da die 0. und 2. Ableitung des Sinus an der Stelle 0 immer 0 sind, kann man optimieren, indem man diese Schritte einfach weglässt, also nur den 1. 3. 5. 7. 9. Es wird immer erst addiert, dann abgezogen (weil 1. Ableitung von sin an der Stelle 0 = 1, 3. Ableitung = -1) Die Zahlen durch die geteilt wird ist die vorberechnete Fakultät von 1, 3, 5, 7, 9, und der Wert dahinter ist das x - 0 hoch k.

Es ist etwas schneller, weil David die Werte jetzt noch so vorberechnet hat, dass weniger Rechenschritte nötig sind.

Werbeanzeige