Multiplizieren Sie mit 0,5, anstatt durch 2 zu dividieren

Lesezeit: 3 Minuten

Nikos Benutzeravatar
Niko

Während ich Tipps in C gelesen habe, habe ich diesen Tipp hier gesehen http://www.cprogramming.com/tips/tip/multiply-rather-than-divide
aber ich bin mir nicht sicher. Mir wurde gesagt, dass sowohl Multiplizieren als auch Dividieren langsamer und zeitaufwändiger sind und viele Zyklen erfordern.

und ich habe Leute oft gesehen i << 2 Anstatt von i x 4 weil das Schalten schneller ist.

Ist es ein guter Tipp mit x0.5 or /2 ? oder aber moderne Compiler optimieren es besser?

  • i * 0.5 ist nicht immer gleich i / 2 (wenn i ist ein intdie Division ist ganzzahlig und nicht Gleitkomma)

    – SheetJS

    10. August 2013 um 18:28 Uhr

  • Sie sollten Ihren Code klar schreiben (i * 4 und i / 2) und aktivieren Sie Compiler-Optimierungen. Compiler sind sehr gut in diesen Optimierungen.

    – Hochofen

    10. August 2013 um 18:34 Uhr

  • Wenn die Profilerstellung einen Leistungsengpass zeigt und Sie bessere Algorithmen und Datenstrukturen ausgewählt haben, beginnen Sie erst dann mit dem Ausprobieren und Testen dieser Mikrooptimierungen. Es ist eine effektivere Nutzung Ihrer Zeit.

    – Hochofen

    10. August 2013 um 18:39 Uhr


  • Ein Ort, an dem solche Optimierungen nicht angewendet werden, ist, wenn Integer div/mod/mul durch eine Nichtkonstante ausgeführt wird. Es hat immer noch einen gewissen Wert, diese Handoptimierungen zu lehren. Bei FP-Mathematik werden diese Optimierungen häufig auch nicht durchgeführt, es sei denn, unsichere Optimierungen werden mit dem Compiler aktiviert.

    – Cory Nelson

    10. August 2013 um 18:39 Uhr

Benutzeravatar von huysentruitw
huysentruitw

Es ist wahr, dass einige (wenn nicht die meisten) Prozessoren schneller multiplizieren können als eine Divisionsoperation, aber es ist wie der Mythos von ++i schneller sein als i++ in einer for-Schleife. Ja, das war es einmal, aber heutzutage sind Compiler schlau genug, all diese Dinge für Sie zu optimieren, also sollten Sie sich nicht mehr darum kümmern.

Und was das Bit-Shiften betrifft, es war früher schneller zu verschieben << 2 als mit 4 zu multiplizieren, aber diese Zeiten sind vorbei, da die meisten Prozessoren in einem Taktzyklus multiplizieren können, genau wie ein Schichtbetrieb.

Ein gutes Beispiel dafür war die Berechnung der Pixeladresse in VGA 320x240 Modus. Das haben sie alle gemacht:

address = x + (y << 8) + (y << 6)

um y mit 320 zu multiplizieren. Auf modernen Prozessoren kann dies langsamer sein als nur:

address = x + y * 320;

Also, schreiben Sie einfach, was Sie denken, und der Compiler erledigt den Rest 🙂

  • Kein mir bekannter Prozessor multipliziert sich in einem Zyklus (Quelle: instlatx64.atw.hu ). (allerdings wird die Multiplikation mit 4 wohl ohnehin vom Compiler auf eine Verschiebung optimiert)

    – Harald

    10. August 2013 um 18:36 Uhr

  • @harold: Die Latenz kann> 1 Zyklus betragen, aber der Durchsatz sollte auf den meisten modernen CPUs 1 Zyklus/Mult betragen …

    – Oliver Charlesworth

    10. August 2013 um 18:39 Uhr


  • Der Mythos ist wahr: ++i ist schneller als i++, zumindest wenn i ein komplexes Objekt ist. cppreference,.com zitieren: “Da eine temporäre Kopie des Objekts während des Post-Increments und Post-Decrements erstellt wird, sind Pre-Increment- oder Pre-Decrement-Operatoren normalerweise effizienter in Kontexten, in denen der zurückgegebene Wert nicht verwendet wird.”

    – Pixelfett

    16. August 2017 um 22:12 Uhr

  • Ich möchte einen neueren Compiler sehen, der nicht intelligent genug ist, um dies zu optimieren, nachdem er erkennt, dass der temporäre Wert nie verwendet wird.

    – huysentruitw

    16. August 2017 um 23:01 Uhr

  • @pixelgrease Obwohl dies eine C-Frage ist.

    – Davislor

    4. September 2018 um 7:05 Uhr

Ich finde, dass dieser Dienst von unschätzbarem Wert ist, um diese Art von Dingen zu testen:

http://gcc.godbolt.org/

Schauen Sie sich nur die Endmontage an. In 99 % der Fälle werden Sie feststellen, dass der Compiler sowieso alles auf denselben Code optimiert. Verschwenden Sie nicht die Gehirnleistung!

In einigen Fällen ist es besser, es explizit zu schreiben. Zum Beispiel, 2^n (wobei n eine positive ganze Zahl ist) könnte geschrieben werden als (int) pow( 2.0, n ) aber es ist offensichtlich besser zu verwenden 1<<n (und der Compiler wird diese Optimierung nicht für Sie vornehmen). Es kann sich also lohnen, diese Dinge im Hinterkopf zu behalten. Wie bei allem sollten Sie jedoch nicht vorzeitig optimieren.

  1. „mit 0,5 multiplizieren statt durch 2 dividieren“ (2,0) geht schneller weniger Umgebungen heute als früher, hauptsächlich aufgrund verbesserter Compiler, die den Code optimieren.

  2. “benutze i << 2 statt ix 4" geht schneller weniger Umgebungen aus ähnlichen Gründen.

  3. Im auswählen In solchen Fällen muss sich der Programmierer immer noch um solche Probleme kümmern, aber es wird immer seltener. Code Wartung wächst weiterhin als dominierendes Thema. Verwenden Sie also das, was für dieses Code-Snippet am sinnvollsten ist: x*0.5, x/2.0, half(x)etc.

  4. Compiler optimieren leicht Code. Empfehlen Sie Code mit High-Level-Problemen im Auge. Z.B. Ist der Algorithmus O(n) oder O(n*n)?

  5. Der wichtige Gedanke, den es weiterzugeben gilt, ist dieser Die besten Code-Design-Praktiken entwickeln sich weiter und Variationen treten unter den Umgebungen auf. Anpassungsfähig sein. Was heute am besten ist, kann sich in Zukunft verschieben (oder vervielfachen).

Benutzeravatar von pukingminion
kotzminion

Viele CPUs können die Multiplikation in 1 oder 2 Taktzyklen durchführen, aber die Division dauert immer länger (obwohl die FP-Division manchmal schneller ist als die Integer-Division).

Wenn Sie sich diese Antwort ansehen Wie kann ich die Leistung von log() und fp division in C++ vergleichen? Sie werden sehen, dass die Teilung 24 Zyklen überschreiten kann.

Warum dauert die Division so viel länger als die Multiplikation? Wenn Sie sich an die Grundschule erinnern, erinnern Sie sich vielleicht, dass Multiplikationen im Wesentlichen mit vielen gleichzeitigen Additionen durchgeführt werden können. Die Division erfordert eine iterative Subtraktion, die nicht gleichzeitig durchgeführt werden kann und daher länger dauert. Tatsächlich beschleunigen einige FP-Einheiten die Division, indem sie eine reziproke Approximation durchführen und damit multiplizieren. Es ist nicht ganz so genau, aber etwas schneller.

Wenn Sie mit Ganzzahlen arbeiten und als Ergebnis eine Ganzzahl erwarten, ist es besser, sie zu verwenden / 2vermeidet auf diese Weise unnötige Konvertierungen nach/von Float

  • Wenn Sie mit ganzen Zahlen arbeiten und als Ergebnis eine ganze Zahl erwarten, >> 1 überlegen ist / 2. Der Compiler kann letztere nicht durch erstere ersetzen, da sie für negative Zahlen nicht äquivalent sind (außer wenn das Ergebnis eine ganze Zahl ist, Wissen, das der Programmierer hat, aber der Compiler möglicherweise nicht in der Lage ist, daraus abzuleiten).

    – Pascal Cuoq

    10. August 2013 um 18:38 Uhr

  • @PascalCuoq das stimmt, aber der Unterschied verschwindet, wenn Sie mit arbeiten unsigned ints, aus offensichtlichen Gründen. Und wenn Sie mit signierten arbeiten ints, Sie möchten wahrscheinlich kein falsches Verhalten für negative Zahlen.

    – David

    10. August 2013 um 18:41 Uhr

  • Es ist nicht falsch, wenn Sie „als Ergebnis eine ganze Zahl erwarten“.

    – Pascal Cuoq

    10. August 2013 um 18:48 Uhr

  • @PascalCuoq ah ich verstehe, was du meinst (ich bin zuerst nicht gefolgt, weil du natürlich immer eine ganze Zahl als Ergebnis bekommst!)

    – David

    10. August 2013 um 20:55 Uhr

  • Wenn Sie mit ganzen Zahlen arbeiten und als Ergebnis eine ganze Zahl erwarten, >> 1 überlegen ist / 2. Der Compiler kann letztere nicht durch erstere ersetzen, da sie für negative Zahlen nicht äquivalent sind (außer wenn das Ergebnis eine ganze Zahl ist, Wissen, das der Programmierer hat, aber der Compiler möglicherweise nicht in der Lage ist, daraus abzuleiten).

    – Pascal Cuoq

    10. August 2013 um 18:38 Uhr

  • @PascalCuoq das stimmt, aber der Unterschied verschwindet, wenn Sie mit arbeiten unsigned ints, aus offensichtlichen Gründen. Und wenn Sie mit signierten arbeiten ints, Sie möchten wahrscheinlich kein falsches Verhalten für negative Zahlen.

    – David

    10. August 2013 um 18:41 Uhr

  • Es ist nicht falsch, wenn Sie „als Ergebnis eine ganze Zahl erwarten“.

    – Pascal Cuoq

    10. August 2013 um 18:48 Uhr

  • @PascalCuoq ah ich verstehe, was du meinst (ich bin zuerst nicht gefolgt, weil du natürlich immer eine ganze Zahl als Ergebnis bekommst!)

    – David

    10. August 2013 um 20:55 Uhr

1433410cookie-checkMultiplizieren Sie mit 0,5, anstatt durch 2 zu dividieren

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

Privacy policy