Gleitkommazahlen



  • Hallo,

    welche Instruktionsklasse (z.B. FPU, ,SSE, SSE2, usw.) sollte man bei Abarbeitung von Gleitkommazahlen verwenden, so wohl für 32-Bit als auch für 64-Bit Systeme, damit die Geschwindigkeit ber Berechnung möglichst optimal wird?
    Ich habe zum Beispiel den Effekt, dass ich auf einem Amd64 die Geschwindigkeit im 32- sowie 64Bit-Modus optimiert habe, aber auf einem Pentium 4 genau das Gegenteil
    erreicht habe.

    Gruß

    Boris


  • Mod

    das kommt drauf an... im zweifel kannst du ja einen codepfad für jede variante anlegen und dann beim programmstart einen kurzen benchmark laufenlassen 🙂
    das verhalten des pentium 4 ist im übrigen recht gewöhnungsbedürftig und muss gut getested werden - es ist relativ leicht code zu schreiben, der auf athlons und dem pentium3 nahezu optimal läuft. aber beim P4 ist das ergebnis dann häufig unbefriedigend. als faustregel gilt, dass zumindest bei alten athlons die fpu deutlich schneller ist; bei pentiums sollte man nach möglichkeit sse verwenden. im 64bit modus stellt sich die frage nicht.



  • Sowas dachte ich mir schon, aber nun gut. Dann auch gleich meine nächste Frage:
    Wie bekomme ich die Übergabeparameter (double) vom Stack-Frame in die XMM-Register im 32-Bit Modus und auch wieder zurück?

    pushl %ebp
    movl %esp, %ebp
    movlsd 8(%ebp), %xmm0 # Klappt nicht


  • Mod

    der befehl heisst movsd (mov (s)calar (d)ouble), nicht movlsd - bin mir nicht sicher, ob da noch ein suffix ran kann (müsste dann movsdl sein), benötigt wird es in keinem fall.



  • Meinte ich auch, da hatte ich mich wohl verschrieben. Aber es klappt leider nicht.

    Code:
    pushl %ebp
    movl %esp, %ebp
    movsd 8(%ebp), %xmm0
    movsd 16(%ebp), %xmm1
    addsd %xmm1, %xmm0
    movsd %xmm0, -8(%ebp)
    fld -8(%ebp)
    movl %ebp, %esp
    popl %ebp
    ret

    Liegt es vielleicht an den movsd-Befehlen?


  • Mod

    definiere klappt nicht. übrigens müste er bei fld -8(%ebp) warnen, hier ist ein suffix angebracht. zeigt doch mal die gesamte funktionsdefinion, sieht ja doch irgendwie wie gcc inline aus... und dann muss das etwas anders aussehen, damit der compiler weiss, was los ist.



  • Ok, mit klappt nicht meinte ich, es kommen falsche Werte raus.
    Im wesentlichen ist die eine Additionsfkt. die später erweitert wird, das
    ich den Rundungsmodus mit berücksichtige.
    Also:

    header-file:
    extern double ra_addu(double,double);

    Assembler-File:

    .globl ra_addu
    .type ra_addu, @function
    ra_addu:
    pushl %ebp
    movl %esp, %ebp
    movsd 8(%ebp), %xmm0
    movsd 16(%ebp), %xmm1
    addsd %xmm1, %xmm0
    movsd %xmm0, -8(%ebp)
    fld -8(%ebp)
    movl %ebp, %esp
    popl %ebp
    ret


  • Mod

    hm, ich schätze es müsste so eigentlich funktionieren, wenn es auch grauenhaft schlechter code ist :p
    du könntest es ja noch mit

    extern "C" double __cdecl ra_addu(double,double);
    

    versuchen.
    in jedem falle kann man hier stark kürzen:

    .globl ra_addu
    .type ra_addu, @function
    ra_addu:
    fldl 4(%esp)
    faddl 12(%esp)
    ret
    

    operanden zwischen xmm in fpu registern hin und her zu schieben ist immer eine ganz ganz schlechte idee...

    mit inline assembler geht es einfacher und flexibler

    inline double asm_add(double lhs, double rhs)
    {
        double sum;
        asm ( "addsd %2, %1":"=x"(sum):"%0"(lhs),"xm"(rhs) );
        return sum;
    }
    

    muss man einfach mögen 🙂


Anmelden zum Antworten