Ich habe kürzlich eine Vector 3-Klasse geschrieben und meine normalize () -Funktion zur Überprüfung an einen Freund gesendet. Er sagte, es sei gut, aber ich sollte mich mit dem Kehrwert multiplizieren, wo es möglich ist, weil "Multiplizieren ist billiger als Dividieren" in der CPU-Zeit.
Meine Frage ist einfach, warum ist das so?
Denken Sie darüber nach, was Elementaroperationen angeht, die die Hardware leichter implementieren kann - Addieren, Subtrahieren, Verschieben, Vergleichen. Die Multiplikation selbst in einer trivialen Anordnung erfordert weniger solche elementaren Schritte - und sie bietet fortschrittliche Algorithmen, die sogar noch schneller sind - siehe hier zum Beispiel ... aber die Hardware nutzt diese im Allgemeinen nicht aus (außer vielleicht extrem spezialisierte Hardware). Zum Beispiel, wie die Wikipedia-URL sagt, "Toom-Cook kann eine Größe-N gewürfelte Multiplikation für die Kosten von fünf Größe-N-Multiplikationen tun" - das ist tatsächlich sehr schnell für sehr große Zahlen (Fürers Algorithmus, eine ziemlich neue Entwicklung, kann Θ(n ln(n) 2Θ(ln*(n)))
- wieder, siehe die Wikipedia-Seite und Links davon.
Division ist nur intrinsisch langsamer, als - wieder - per wikipedia ; selbst die besten Algorithmen (von denen einige in HW implementiert sind, nur weil sie nirgendwo so anspruchsvoll und komplex sind wie die besten Algorithmen zur Multiplikation ;-) können die Multiplikationen nicht ertragen.
Nur um das Problem mit nicht so großen Zahlen zu quantifizieren, hier sind einige Ergebnisse mit gmpy , einem einfachen zu verwenden Python-Wrapper um GMP , die tendenziell ziemlich gute Implementierungen von Arithmetik haben, obwohl nicht unbedingt die neuesten und größten Keuchen. Auf einer langsamen (; ersten Generation ;-) Macbook Pro:
%Vor%Wie Sie sehen, kann die Multiplikation mit dem Kehrwert selbst bei dieser kleinen Größe (Anzahl der Bits in den Zahlen) und bei Bibliotheken, die von genau den gleichen geschwindigkeitsbesessenen Menschen optimiert werden, 1/3 der Zeit, die die Division benötigt, einsparen.
Es kann nur in seltenen Situationen sein, dass diese paar Nanosekunden ein Leben-oder-Tod-Problem sind, aber wenn sie sind , und natürlich wenn Sie wiederholt durch den gleichen Wert teilen (to amortisieren Sie die Operation 1.0/b
!), dann kann dieses Wissen ein Lebensretter sein.
(Sehr ähnlich - x*x
spart oft Zeit im Vergleich zu x**2
[in Sprachen, die einen **
"Raise to Power" -Operator haben, wie Python und Fortran] - und Horner's Schema für die Polynomberechnung ist VATERY gegenüber wiederholten Raise-to-Power Operationen vorzuziehen! -).
Wenn Sie an die Grundschule denken, werden Sie sich daran erinnern, dass die Multiplikation schwieriger war als die Addition und die Division schwieriger war als die Multiplikation. Die Dinge sind nicht anders für die CPU.
Erinnern Sie sich auch daran, dass die Berechnung des Reziproken eine Division beinhaltet. Wenn Sie also das Reziproke nicht einmal berechnen und dreimal verwenden, sehen Sie keine Beschleunigung.
Die CPU-Operation für (float) Division ist viel komplizierter als Multiplikation. Die CPU muss mehr tun. Ich bin weit entfernt von Hardware-Kenntnissen, aber Sie können viele Informationen über die gemeinsame Implementierung von Divisionen finden (basierend auf newton-raphson Algorithmen zum Beispiel).
Ich würde auch darauf achten, immer die Multiplikation der reziproken anstelle der Division zu verwenden, um CPU-Leistung zu erhalten: Sie geben möglicherweise nicht genau die gleichen Ergebnisse. Dies kann oder kann nicht von Bedeutung für Ihre Anwendung sein.
Tags und Links performance cpu-usage theory