3 Stimmen

Benchmarking von math.h Quadratwurzel und Quake Quadratwurzel

Okay, ich war also an Bord und fragte mich, wie schnell math.h square Root im Vergleich zu der mit der magischen Zahl darin war (berühmt geworden durch Quake, aber von SGI gemacht).

Aber das hat mich in eine Welt des Schmerzes geführt.

Ich habe das zuerst auf dem Mac ausprobiert, wo die math.h jedes Mal gewonnen hat, und dann auf Windows, wo die magische Zahl immer gewonnen hat, aber ich denke, das ist alles auf meine eigene Unwissenheit zurückzuführen.

  1. Kompilieren auf dem Mac mit "g++ -o sq_root sq_root_test.cpp", wenn das Programm ausgeführt wird, dauert es etwa 15 Sekunden zu beenden. Aber das Kompilieren in VS2005 auf Release dauert einen Sekundenbruchteil. (Tatsächlich musste ich das Programm im Debug-Modus kompilieren, nur damit es ein paar Zahlen anzeigt)

  2. Mein armes Benchmarking? ist das wirklich dumm? denn ich erhalte 0,01 für math.h und 0 für die Magic number. (es kann nicht so schnell sein, kann es?)

Ich weiß nicht, ob das eine Rolle spielt, aber der Mac hat einen Intel-Prozessor und der PC einen AMD-Prozessor. Verwendet der Mac Hardware für math.h sqroot?

Ich habe den schnellen Quadratwurzel-Algorithmus von http://en.wikipedia.org/wiki/Fast_inverse_square_root

//sq_root_test.cpp

#include <iostream>
#include <math.h>
#include <ctime>

float invSqrt(float x)
{
    union {
        float f;
        int i;
    } tmp;
    tmp.f = x;
    tmp.i = 0x5f3759df - (tmp.i >> 1);
    float y = tmp.f;
    return y * (1.5f - 0.5f * x * y * y);
}

int main() {
    std::clock_t start;// = std::clock();
    std::clock_t end;
    float rootMe;

    int iterations = 999999999;

    // ---

    rootMe = 2.0f;
    start = std::clock();

    std::cout << "Math.h SqRoot: ";

    for (int m = 0; m < iterations; m++) {
        (float)(1.0/sqrt(rootMe));
        rootMe++;
    }

    end = std::clock();

    std::cout << (difftime(end, start)) << std::endl;

    // ---

    std::cout << "Quake SqRoot: ";

    rootMe = 2.0f;
    start = std::clock();

    for (int q = 0; q < iterations; q++) {
        invSqrt(rootMe);
        rootMe++;
    }

    end = std::clock();

    std::cout << (difftime(end, start)) << std::endl;   
}

6voto

jalf Punkte 235501

Es gibt mehrere Probleme mit Ihren Benchmarks. Erstens beinhaltet Ihr Benchmark einen potentiell teuren Cast von int nach float. Wenn Sie wissen wollen, was eine Quadratwurzel kostet, sollten Sie Quadratwurzeln benchmarken, nicht Datentypkonvertierungen.

Zweitens kann Ihr gesamter Benchmark (und es ), die vom Compiler optimiert wurde, weil sie keine sichtbaren Nebenwirkungen hat. Sie verwenden den zurückgegebenen Wert nicht (oder speichern ihn an einer flüchtigen Speicherstelle), so dass der Compiler sieht, dass es kann die ganze Sache überspringen .

Ein Hinweis darauf ist, dass Sie die Optimierungen deaktivieren mussten. Das bedeutet, dass Ihr Benchmarking-Code fehlerhaft ist. Niemals immer Optimierungen beim Benchmarking zu deaktivieren. Sie wollen wissen, welche Version am schnellsten läuft, also sollten Sie sie unter den Bedingungen testen, unter denen sie tatsächlich verwendet wird. Wenn Sie Quadratwurzeln in leistungsempfindlichem Code verwenden würden, würden Sie die Optimierungen aktivieren, damit Sie wissen, wie sie sich verhalten ohne Optimierungen ist völlig irrelevant.

Außerdem bewerten Sie nicht die Kosten für die Berechnung einer Quadratwurzel, sondern die Kosten für die Invers Quadratwurzel. Wenn Sie wissen wollen, welcher Weg zur Berechnung der Quadratwurzel am schnellsten ist, müssen Sie die 1.0/... bis hin zur Quake-Version. (Und da Division eine ziemlich teure Operation ist, könnte dies einen großen Unterschied in Ihren Ergebnissen machen)

Abschließend sei noch darauf hingewiesen, dass Carmacks kleiner Trick für 12 Jahre alte Computer entwickelt wurde, um schnell zu sein. Wenn Sie Ihren Benchmark korrigieren, werden Sie wahrscheinlich feststellen, dass es sich nicht mehr um eine Optimierung handelt, da die heutigen CPUs bei der Berechnung von "echten" Quadratwurzeln viel schneller sind.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X