Ruby 3.0 macht x ** 2 schneller

x ** 2 ist langsam

Angenommen, die Variable x enthält eine Zahl wie Integer oder Float. Die Berechnung des Quadrats von "x" ist

x ** 2

Aber wenn Sie so schnell wie möglich rechnen wollen

x * x

Du solltest schreiben. Letzteres ist bei weitem das schnellste. Ersteres ist langsam.

Prüfstandstest

Zuerst

gem install benchmark_driver

Installieren Sie dann Benchmark_driver und installieren Sie es.

square.yaml


prelude: |
  x = 3.0
benchmark:
  - "x ** 2"
  - "x * x"

Bereiten Sie eine YAML-Datei mit dem Namen vor

benchmark-driver square.yaml

Sie können es mit vergleichen.

Gemessen mit "Ruby 2.7.1p83 (2020-03-31 Revision a0c7c23c9c) [x86_64-darwin17]" sind die Ergebnisse wie folgt.

     x * x:  92940175.9 i/s 
    x ** 2:  15605744.0 i/s - 5.96x  slower

Beeindruckend!

Nun, selbst wenn es langsam ist, kann es 15 Millionen Mal pro Sekunde ausgeführt werden, daher ist diese Langsamkeit nur dann ein Problem, wenn viele numerische Berechnungen durchgeführt werden [^ sp].

[^ sp]: Wenn Sie ein Programm beschleunigen möchten, ist es wichtig, die Zahlen durch einen Benchmark-Test richtig zu verfolgen, und es ist sinnlos, die Blutlinie zu erhöhen, um den Teil zu optimieren, der die Ausführungszeit des gesamten Programms nicht beeinflusst. Ich möchte daran denken.

Verbessert mit Ruby 3.0

Es wurden Änderungen vorgenommen, um "** 2" speziell für Float zu behandeln und schneller zu berechnen. Sie können dies mit Ruby 3.0.0-Preview1 überprüfen.

Wenn Sie Ruby in rbenv haben, können Sie es einfach mit Benchmark_Driver testen. Diesmal für dieselbe YAML-Datei wie zuvor

benchmark-driver square.yaml --rbenv "2.7.2;3.0.0-preview1"

Und. Die Ergebnisse sind wie folgt.

                       x ** 2
  3.0.0-preview1:  37039739.4 i/s 
           2.7.2:  16010580.7 i/s - 2.31x  slower

                        x * x
           2.7.2:  91881050.6 i/s 
  3.0.0-preview1:  88138626.5 i/s - 1.04x  slower

"x * x", eher "3.0.0-Vorschau1" ist langsamer, aber dies liegt im Fehlerbereich. x ** 2 ist 2,3 mal schneller.

Impressionen

Nun, "x * x" ist immer noch mehr als doppelt so schnell wie "x ** 2", aber ich denke, es ist immer noch eine wichtige Entwicklung. Es gibt viele Codes wie "x ** 2" und sie machen es schneller, ohne etwas zu tun.

In einigen Fällen möchten Sie möglicherweise "** 2" auf Kosten der Geschwindigkeit verwenden. In diesem Fall befindet sich der Ausdruck, den Sie quadrieren möchten, nicht in der Variablen. Nun, diese Art von Bild:

items.map.with_index{ |item, i| (a * item.value + b[i]) ** 2 }

Dies

items.map.with_index{ |item, i| (a * item.value + b[i]) * (a * item.value + b[i]) }

Es ist nicht nur redundant, sondern verlangsamt es wahrscheinlich auch. Sobald Sie den Wert des Ausdrucks in eine Variable eingefügt haben

items.map.with_index{ |item, i| x = a * item.value + b[i]; x * x }

Wird geschrieben werden. Wenn Geschwindigkeit die höchste Priorität hat, würde ich es so schreiben, aber wenn Sie sagen "Ich möchte Geschwindigkeit, aber ich möchte auch Einfachheit", könnte ich "** 2" verwenden.

Recommended Posts

Ruby 3.0 macht x ** 2 schneller
Edelsteinliste für jede Ruby-Version 2.5.x.
[Java] Machen Sie das Programm mit parallelStream 10x schneller
CentOS8.2 (x86_64) + ruby2.5 + Rails5.2 + MariaDB (10.3.17) Umgebungskonstruktion