C++Guns – RoboBlog

12.10.2018

C++ Guns: -Ofast in action

Filed under: Allgemein — Tags: — Thomas @ 10:10

Mit -Ofast wird bei folgenden Code die Power Funktion weg optimiert und durch die dritte Wurzel ersetzt.

auto func(double MANNING2, double qNorm, double H ) {
    return MANNING2 * qNorm / (pow(H,(7.0/3.0)));
}

Im Assembler Code ist nur noch cbrt zu erkennen, kein pow mehr.

func(double, double, double):
        subq    $40, %rsp
        movsd   %xmm0, 8(%rsp)    # MANNING2
        movapd  %xmm2, %xmm0      # H nach xmm0 für cbrt
        movsd   %xmm1, 24(%rsp)   # qNorm
        movsd   %xmm2, 16(%rsp)   # H
        call    cbrt              # cbrt(H) nach xmm0
        movsd   16(%rsp), %xmm2   # xmm2 = H
        movsd   24(%rsp), %xmm1   # xmm1 = qNorm
        mulsd   8(%rsp), %xmm1    # xmm1 = MANNING2*qNorm
        addq    $40, %rsp 
        mulsd   %xmm2, %xmm2      # xmm2 = H*H
        mulsd   %xmm0, %xmm2      # xmm2 = H*H*cbrt(H)
        divsd   %xmm2, %xmm1      # xmm1 = MANNING2*qNorm /(H*H*cbrt(H))
        movapd  %xmm1, %xmm0
        ret

Der Assembler Code zurück nach C++ übersetzt gibt folgenden:

auto func(double MANNING2, double qNorm, double H ) {
    return MANNING2 * qNorm / (H*H*cbrt(H));
}

Die pow Funktion mit zwar bekannten, aber "unschönen" Exponenten wurde ersetzt durch eine Multiplikation und eine Power Funktion mit bekannte und "schönen" Exponenten: 1/3

Aber es könnte besser sein. Es fällt auf, dass die Funktionsargumente erst einmal auf den Stack gepusht werden. Offenbar braucht die cbrt Funktion die Register xmm0, xmm1, xmm2 selbst. Und so müssen die Werte eben gesichert werden. Da sie erst danach gebraucht werden. ...
Natürlich kann man MANNING2*qNorm berechnen bevor vor Nenner der Formel fertig berechnet ist. Mathematisch kann man das tun, die Klammern kann man setzten.

Aber den Compiler stört das nicht. Es wird immer erst cbrt vor MANNING2*qNorm. Ich denke cbrt braucht einfach mehr Zeit als eine Multiplikation. Und daher wird dieser Befehl als erstes ausgeführt. Und zwischenzeitlich können davon unabhängige Variablen bearbeitet werden.

Aber eine Sache kann dennoch optimiert werden. Indem H als ersten Parameter übergeben wird. Dann liegt es gleich im xmm0 Register für cbrt bereit und muss nicht erst dorthin kopiert werden. An der Anzahl der Instruktionen ändert dies nichts. Aber die mov Operation wird auch erst nach cbrt ausgeführt.

No Comments

No comments yet.

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Powered by WordPress