sinus / cosinus



  • Gut, passt vieleicht bisschen schlecht ins C++ Forum, is aber inline Assembler.

    1. Ich suche den Inline Assembler Quellcode einer cos, sin, tan Funktion(nach möglichkeit x86)

    2. Ist die Prozessorklasse wichtig? 😕

    Die hier habe ich mal im Internet gefunden:

    inline const float sqrt(const float& value)
    {
    	float result;
    
    	_asm
    	{
    		mov eax, value
    		sub eax, 0x3f800000
    		sar eax, 1
    		add eax, 0x3f800000
    		mov result, eax
    	}
    
    	return(result);
    }
    

    --> ist auch einiges schneller, als die sqrt aus <cmath>

    3. Weiß jemand, warum?
    4. Kann man die Funktion noch optimieren? 😕


  • Mod

    Tc++H schrieb:

    Gut, passt vieleicht bisschen schlecht ins C++ Forum, is aber inline Assembler.

    und wozu ist wohl das assemblerforum da?

    1. Ich suche den Inline Assembler Quellcode einer cos, sin, tan Funktion(nach möglichkeit x86)

    2. Ist die Prozessorklasse wichtig? 😕

    sie beeinflußt die auswahl, also ja.

    Die hier habe ich mal im Internet gefunden:

    --> ist auch einiges schneller, als die sqrt aus <cmath>
    3. Weiß jemand, warum?

    weil sie nicht die wurzel berechnet.

    4. Kann man die Funktion noch optimieren? 😕

    schon möglich. was willst du denn daran optimieren?



  • camper schrieb:

    Tc++H schrieb:

    Gut, passt vieleicht bisschen schlecht ins C++ Forum, is aber inline Assembler.

    und wozu ist wohl das assemblerforum da?

    Hey, komm schon... Er benutzt doch nichtmal 'nen Lötkolben... 😃

    Tc++H schrieb:

    1. Ich suche den Inline Assembler Quellcode einer cos, sin, tan Funktion(nach möglichkeit x86)

    Ich find x86 für diese Aufgabe etwas... naja, wie soll ich's sagen... deplaziert

    Tc++H schrieb:

    Die hier habe ich mal im Internet gefunden:

    inline const float sqrt(const float& value)
    {
    	float result;
    
    	_asm
    	{
    		mov eax, value
    		sub eax, 0x3f800000
    		sar eax, 1
    		add eax, 0x3f800000
    		mov result, eax
    	}
    
    	return(result);
    }
    

    --> ist auch einiges schneller, als die sqrt aus <cmath>

    3. Weiß jemand, warum?

    *lol*

    Tc++H schrieb:

    4. Kann man die Funktion noch optimieren? 😕

    Ne, die Funktion nicht 😉

    Ich würd ja den 80x87 (AKA Math Coprocessor) vorschlagen:

    #include <iostream>
    
    using namespace std;
    
    double sine( double x )
    {
        __asm {
            FNINIT  ; Coprozessor initialisieren
            FLD x   ; x nach ST( 0 )
            FSIN    ; sinus davon
        }
    } // ST( 0 ) - Ergebnis von FSIN - wird zurückgegeben
    
    int main( )
    {
        double x = 0.9;
        cout << "sin( " << x << " ) = " << sine( x ) << endl;
    }
    

    Greetz, Swordfish

    PS: Und, was sagt ihr zu meinem allerersten Assemblerprogramm für den 80x87? 😃



  • Hab' grad mal 'ne Laufzeitmessung gemacht. Erschreckend:

    #include <iostream>
    #include <cmath>
    #include <cstdlib>
    #include <ctime>
    
    #include <windows.h>
    
    using namespace std;
    
    __forceinline double sine( double x )
    {
        __asm {
            FNINIT
            FLD x
            FSIN
        }
    }
    
    int main( )
    {
        srand( static_cast< unsigned int >( time( 0 ) ) );
    
        double x[ 1000 ];
    
        for( register unsigned int i = 0; i < 1000; ++i ) {
            x[ i ] = ( 10000.0 * rand( ) / static_cast< float >( RAND_MAX ) ) /
                     ( 10000.0 * rand( ) / static_cast< float >( RAND_MAX ) );
        }
    
        __int64 pc_freq, start, stop;
    
        QueryPerformanceFrequency( reinterpret_cast< LARGE_INTEGER* >( &pc_freq ) );
        QueryPerformanceCounter( reinterpret_cast< LARGE_INTEGER* >( &start ) );
    
        for( register unsigned int i = 0; i < 1000; ++i )
            sine( x[ i ] );
    
        QueryPerformanceCounter( reinterpret_cast< LARGE_INTEGER* >( &stop ) );
    
        double total_time = ( static_cast< double >( stop - start ) / pc_freq ) * 1000.0;
        cout << "Total time elapsed ( 1000 calls to sine( ) ): " << fixed << total_time << " ms" << endl;
        cout << "Average time elapsed per call: " << fixed << total_time << " us" << endl << endl;
    
        QueryPerformanceCounter( reinterpret_cast< LARGE_INTEGER* >( &start ) );
    
        for( register unsigned int i = 0; i < 1000; ++i )
            sin( x[ i ] );
    
        QueryPerformanceCounter( reinterpret_cast< LARGE_INTEGER* >( &stop ) );
    
        total_time = ( static_cast< double >( stop - start ) / pc_freq ) * 1000.0;
        cout << "Total time elapsed ( 1000 calls to sin( ) ): " << fixed << total_time << " ms" << endl;
        cout << "Average time elapsed per call: " << fixed << total_time << " us" << endl << endl;
    }
    

    Befehlszeile:

    /O2 /Og /Ob2 /Oi /Ot /Oy /GL /G5 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /GF /FD /EHsc /ML /GS /Fo"Release/" /Fd"Release/vc70.pdb" /W4 /WX /nologo /c /Wp64 /Gd /TP
    

    Output:

    Total time elapsed ( 1000 calls to sine( ) ): 0.166502 ms
    Average time elapsed per call: 0.166502 us
    
    Total time elapsed ( 1000 calls to sin( ) ): 0.002514 ms
    Average time elapsed per call: 0.002514 us
    

    Da sollte wohl doch eher SSE, SSE2, 3DNOW etc. dran 😃

    Greetz, Swordfish


  • Mod

    Swordfish schrieb:

    PS: Und, was sagt ihr zu meinem allerersten Assemblerprogramm für den 80x87? 😃

    sehr hübsch. 🙂

    Swordfish schrieb:

    Hab' grad mal 'ne Laufzeitmessung gemacht. Erschreckend:

    assembler ist zwar low-level aber deswegen nicht unbedingt einfach. 👍



  • Meinst du, man könnte die CRT mit SSE und Kohorten überflügeln?

    Greetz, Swordfish


  • Mod

    nein. gib dem compiler die richtigen switches und der benutzt sowieso intrinsics. schon der versuch dieser microoptimierung von primitiven muss fehlschlagen.


Anmelden zum Antworten