Ist es möglich, eine deutlich schnellere Version von sqrt zu rollen
-
26-09-2019 - |
Frage
In einer App Ich bin Profilieren, fand ich in einigen Szenarien, dass diese Funktion der Lage ist, 10% der gesamten Ausführungszeit zu übernehmen.
Ich habe die Jahre gesehen Diskussion über schnellere sqrt Implementierungen mit hinterhältigen Gleitkommazahlen Tricks, aber ich weiß nicht, ob solche Dinge auf modernen CPUs veraltet sind.
MSVC ++ 2008-Compiler verwendet wird, als Referenz ... obwohl ich davon ausgehen würde sqrt wird nicht fügen viel Aufwand aber.
Sehen Sie hier auch für ähnliche Diskussion auf diese ist eine weit verbreitete Methode, aber ist es wirklich viel schneller? Wie viele Zyklen ist SQRT ohnehin in diesen Tagen?
Lösung
Ja, es ist möglich, auch ohne Tricks:
1) Opfer Genauigkeit für Geschwindigkeit. Der sqrt-Algorithmus ist iterativ, neu implementieren mit weniger Iterationen
2) Lookup-Tabellen:. Entweder nur für den Startpunkt der Iteration, oder in Kombination mit Interpolation Ihnen die ganzen Weg dorthin zu gelangen
3) Caching: Sie sind immer sqrting den gleichen begrenzten Satz von Werten? wenn ja, kann Caching gut funktionieren. Ich habe in Grafikanwendungen dies nützlich gefunden, wo die gleiche Sache für viele Formen der gleiche Größe berechnet wird, so können die Ergebnisse sinnvollerweise im Cache gespeichert werden.
Andere Tipps
Es gibt eine große Vergleichstabelle hier: http://assemblyrequired.crashworks.org/timing-square-root/
Lange Rede kurzer Sinn, SSE2 der ssqrts ist etwa 2x schneller als FPU fsqrt und eine Annäherung + Iteration ist etwa 4-fach schneller als die (8x insgesamt).
Auch wenn Sie versuchen, eine Single-Precision sqrt zu nehmen, stellen Sie sicher, dass die eigentlich das, was Sie bekommen. Ich habe von mindestens einem Compiler gehört, dass der Schwimmer Argument zu einem doppelten, rufen Sie mit doppelter Genauigkeit sqrt umwandeln würde, dann float konvertieren zurück.
Sie sind sehr wahrscheinlich, indem Sie Ihre Algorithmen mehr Verbesserungen in der Geschwindigkeit zu gewinnen als durch Änderung ihrer Implementierungen : Versuchen Sie, Anruf sqrt()
weniger statt Anrufe schneller. (Und wenn Sie denken, dies nicht möglich ist - die Verbesserungen für sqrt()
Sie erwähnen, sind genau das: Verbesserungen des Algorithmus verwendet, um eine Quadratwurzel zu berechnen.)
Da es sehr häufig verwendet wird, ist es wahrscheinlich, dass Ihre Standard-Bibliothek Implementierung von sqrt()
ist nahezu optimal für den allgemeinen Fall. Es sei denn, Sie eine eingeschränkte Domain (zum Beispiel, wenn Sie weniger Präzision benötigen), wo der Algorithmus einiger Abkürzungen nehmen, dann ist es sehr unwahrscheinlich, jemand mit einer Implementierung kommt, der schneller ist.
Beachten Sie, dass, da diese Funktion 10% Ihrer Ausführungszeit verwendet, auch wenn es Ihnen gelingt, mit einer Implementierung zu kommen, dass nur 75% der Zeit von std::sqrt()
nimmt, wird dies nur noch Ihre Ausführungszeit bringen von 2,5% . Für die meisten Anwendungen Benutzer wäre dies nicht einmal bemerken, es sei denn, sie eine Uhr zu messen verwenden.
Wie genau müssen Sie Ihre sqrt
zu sein? Sie können sehr schnell vernünftige Annäherungen erhalten: siehe Quake3 ausgezeichneten inverse Quadratwurzel Funktion für Inspiration (beachten Sie, dass der Code ist GPL'ed, so dass Sie nicht direkt integrieren möchten).