Ist die Multiplikation schneller als die Float-Division? [duplicate]

Lesezeit: 7 Minuten

Benutzeravatar von wodesuck
wosuck

In C/C++ können Sie den folgenden Code einrichten:

double a, b, c;
...
c = (a + b) / 2;

Das macht genau dasselbe wie:

c = (a + b) * 0.5;

Ich frage mich, was besser zu verwenden ist. Ist eine Operation grundsätzlich schneller als die andere?

  • Im Allgemeinen tun sie nicht dasselbe.

    – R.Martinho Fernandes

    26. Juli 2013 um 13:56 Uhr


  • @GrijeshChauhan Schnell sagen? Was ist das um?

    – Grant Thomas

    26. Juli 2013 um 13:58 Uhr

  • @JanSpurny: Dies ist nicht stark CPU- oder architekturabhängig. Es ist teilweise CPU- oder architekturabhängig. Die Multiplikation ist auf vielen Prozessoren viel schneller als die Division, und Programmierer sollten die Multiplikation der Division vorziehen, wenn es keinen anderen Grund gibt.

    – Eric Postpischil

    26. Juli 2013 um 14:12 Uhr


  • Die Stimmen dagegen und die Stimmen zum Schließen sind unangemessen. Dies ist eine gute Frage mit erheblichen Auswirkungen auf die Leistung. Hochleistungscode bevorzugt häufig die Multiplikation gegenüber der Division, da die Multiplikation auf den meisten modernen Prozessoren schneller ist.

    – Eric Postpischil

    26. Juli 2013 um 14:13 Uhr

  • Ein weiterer Grund, warum dies eine wichtige Frage ist (also abstimmen), ist folgender der Optimierer kann diese Transformation nicht durchführen, außer wenn der Faktor eine Zweierpotenz ist (oder, wenn nicht-binäre Gleitkommazahlen verwendet werden, eine Zahl mit einer Umkehrung im Gleitkommasystem ist). Wenn der Faktor im Gleitkommasystem keine exakte Umkehrung hat, darf der Optimierer die Division nicht in eine Multiplikation ändern. Daher sollten sich Programmierer bewusst sein, dass die Multiplikation schneller ist als die Division, und sie sollten die Multiplikation bevorzugen, wenn sie wissen, dass der Rundungsfehler in der Umkehrung akzeptabel ist.

    – Eric Postpischil

    26. Juli 2013 um 14:42 Uhr


Benutzeravatar von Philip Couling
Philipp Couling

Multiplikation ist schneller als Division. An der Universität wurde mir beigebracht, dass die Division das Sechsfache der Multiplikation dauert. Die tatsächlichen Timings sind architekturabhängig, aber im Allgemeinen wird die Multiplikation niemals langsamer oder sogar so langsam wie die Division sein. Optimieren Sie Ihren Code immer auf die Verwendung der Multiplikation, wenn die Rundungsfehler dies zulassen.

In einem Beispiel wäre dies also normalerweise langsamer …

for (int i=0; i<arraySize; i++) {
    a[i] = b[i] / x;
}

… als das …

y=1/x;
for (int i=0; i<arraySize; i++) {
    a[i] = b[i] * y;
}

Natürlich verlieren Sie bei Rundungsfehlern (ein wenig) an Genauigkeit bei der zweiten Methode, aber es sei denn, Sie rechnen wiederholt x=1/x; Das wird wahrscheinlich keine großen Probleme verursachen.

Bearbeiten:

Nur als Referenz. Ich habe einen Drittanbieter-Vergleich der Betriebszeiten ausgegraben, indem ich bei Google gesucht habe.

http://gmplib.org/~tege/x86-timing.pdf

Sehen Sie sich die Zahlen auf MUL und DIV an. Das bedeutet je nach Prozessor Unterschiede zwischen dem 5- und 10-fachen.

  • Kann nicht verstehen, warum das so oft abgelehnt wurde“, weil bei SO jede Frage, die auch nur annähernd undefiniertem/unspezifiziertem/implementierungsabhängigem Verhalten nahe kommt, wahrscheinlich sofort herabgestimmt, geschlossen und unter den Teppich gekehrt wird. Anscheinend ist Pedanterie relevanter als realistische und pragmatische Entwicklungsanforderungen. Leicht ironisch aber manchmal fühlt es sich so an.

    – Thomas

    26. Juli 2013 um 14:14 Uhr


  • @Thomas ja. Ärgerlich ist, dass dies nicht einmal mehrdeutig oder undefiniert ist. Prozessorhersteller veröffentlichen normalerweise die Statistiken. Hierher kommen die Statistiken für Compiler, um die Optimierungen durchzuführen. Hier bedeutet “undefined” also “ich habe es nicht gelesen”. aaarrrrrrr. Okay.

    – Philip Couling

    26. Juli 2013 um 14:27 Uhr

  • @Thomas: Ich würde vermuten, dass die Abwertungen von der Tatsache herrühren, dass die Frage ziemlich trivial ist und ein exaktes Duplikat hat, das automatisch in der Spalte “Verwandt” rechts angezeigt wird (gelesen als: kein Forschungsaufwand), die Optimierung hat einen hohen Wert Wahrscheinlichkeit verfrüht (denken Sie an Ausführung außerhalb der Reihenfolge und Speicherbandbreite), und das Code-Snippet enthält implizite int-double-Konvertierungen und zusätzliche Operationen, die nichts mit der Frage zu tun haben. (Das ist natürlich nur eine Vermutung, ich gehöre nicht zu den Downvotern, kann es also nicht sagen)

    – Dämon

    26. Juli 2013 um 15:22 Uhr


  • @Thomas: Ich neige dazu, mit Neulingen schonend umzugehen. Wir alle machen oder haben zumindest an der einen oder anderen Stelle Fehler gemacht, und dafür versengt zu werden, gibt niemandem das Gefühl, willkommen zu sein. Weniger erfahrenen Menschen zu helfen, ist eine gute Sache, und StackOverflow ist sehr gut darin.

    – Mike Dunlavey

    26. Juli 2013 um 17:14 Uhr

  • Für x86 siehe agner.org/optimieren. div und mul haben unterschiedliche Verhältnisse von Durchsatz zu Latenz. Beide sind nur 1 uop, können sich also gut mit anderen Operationen überschneiden. Ihr ~ 6x teurer sieht für den Durchsatz ungefähr richtig aus, aber das Latenzverhältnis liegt heutzutage für FP div eher bei 4 (auf Intel Haswell). Intel Skylake hat eine sehr stark gepipelinete FP-Div-Einheit (Durchsatz von einem double Ergebnis pro 4 Zyklen). (256b-SIMD-Vektoren haben einen geringeren Durchsatz).

    – Peter Cordes

    4. März 2016 um 10:32 Uhr


Benutzeravatar von Mats Petersson
Matt Petersson

Es ist sehr wahrscheinlich, dass der Compiler in diesem Fall eine Division in eine Multiplikation umwandelt, wenn er “denkt”, dass er schneller ist. Die Division durch 2 in Gleitkommazahlen kann auch schneller sein als andere Float-Divisionen. Wenn der Compiler es nicht konvertiert, kann es schneller sein, multiplizieren zu verwenden, aber nicht sicher – hängt vom Prozessor selbst ab.

Der Gewinn durch die manuelle Verwendung von Multiplizieren statt Dividieren kann ziemlich groß sein, wenn der Compiler nicht feststellen kann, dass dies “sicher” ist (zB 0,1 kann nicht genau als 0,1 in einer Gleitkommazahl gespeichert werden, es wird 0,10000000149011612 ). Nachfolgend finden Sie Zahlen zu AMD-Prozessoren, die als repräsentativ für die Klasse angesehen werden können.

Um festzustellen, ob Ihr Compiler dies gut macht oder nicht, warum schreiben Sie nicht ein bisschen Code zum Experimentieren. Stellen Sie sicher, dass Sie es so schreiben, dass der Compiler nicht nur einen konstanten Wert berechnet und alle Berechnungen in der Schleife verwirft.

Bearbeiten:

Der Optimierungsleitfaden von AMD für Prozessoren der Familie 15h liefert Zahlen für fdiv und fmul sind 42 bzw. 6. SSE-Versionen sind etwas näher, 24 (einfach) oder 27 (doppelt) Zyklen für DIVPS, DIVPD, DIVSS und DIVSD (Teilen) und 6 Zyklen für alle Formen der Multiplikation.

Aus dem Gedächtnis sind die Zahlen von Intel gar nicht so weit weg.

  • Was zum Teufel habe ich jetzt falsch verstanden, dass ich für die Bereitstellung weiterer Informationen herabgestuft werde? Bitte sagt es mir, damit ich es lernen kann!

    – Mats Petersson

    26. Juli 2013 um 14:50 Uhr

  • Ich habe nicht abgelehnt, ich habe keine Ahnung, warum jemand anderes es getan hat, aber ich hoffe, es macht Ihnen nichts aus, dass ich Ihre Aussage korrigiert habe 0.1.

    – Jason

    26. Juli 2013 um 14:56 Uhr

  • Es ist nicht ganz klar, was Sie im zweiten Absatz meinen (die Klammer wird nie geschlossen, und der Satz läuft irgendwie ab. Aber wie in den Kommentaren zu anderen Antworten darauf hingewiesen wurde, konvertiert der Compiler normalerweise keine Divisionen in Multiplikationen, wenn Umgang mit Fließkommacode.

    – jalf

    26. Juli 2013 um 15:03 Uhr

  • @Jalf: Ja, ich habe den zweiten Absatz etwas präzisiert.

    – Mats Petersson

    26. Juli 2013 um 15:30 Uhr

Benutzeravatar von ouah
ouah

Die Fließkommamultiplikation dauert normalerweise weniger Zyklen als die Fließkommadivision. Aber bei Literaloperanden ist sich der Optimierer dieser Art von Mikrooptimierungen wohl bewusst.

  • Dies ist eine Situation, in der wir uns nicht auf den Optimierer verlassen können, wenn wir nach anderen Fällen als einem einzelnen Beispiel in der Frage fragen. Die Division durch eine Zweierpotenz und die Multiplikation mit dem Inversen sind in binären Gleitkommazahlen äquivalent, aber Divisionen durch andere Faktoren haben keine äquivalente Multiplikation, da der Kehrwert nicht genau dargestellt werden kann. Dies verhindert, dass der Optimierer die Transformation durchführt. Daher sollten sich Programmierer dessen bewusst sein und die Multiplikation bevorzugen, wenn sie wissen, dass der Rundungsfehler in der Umkehrung akzeptabel ist.

    – Eric Postpischil

    26. Juli 2013 um 14:16 Uhr


  • @EricPostpischil: Hilft es, Flags für “schnelle Mathematik verwenden” in Fällen zu geben, in denen wir uns nicht zu sehr um Präzision kümmern? Sagen Sie zum Beispiel im Fall von 3D-Spielen, dass Sie erwarten würden, dass die letzten paar Bits der Fließkommapräzision keine Rolle spielen.

    – Mats Petersson

    26. Juli 2013 um 14:24 Uhr

  • x/y —> x * (1/y) ist lizenziert von -ffast-math. Insbesondere ist dies lizenziert von -freciprocal-mathdie eine der „Optimierungen“ ist, die in enthalten sind -ffast-math.

    – Stefan Kanon

    26. Juli 2013 um 14:59 Uhr


1420800cookie-checkIst die Multiplikation schneller als die Float-Division? [duplicate]

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy