Ruby 3.0 rend x ** 2 plus rapide

x ** 2 est lent

Supposons que la variable «x» contienne un nombre tel que Integer ou Float. Le calcul du carré de «x» est

x ** 2

Mais si vous voulez calculer le plus vite possible

x * x

Vous devriez écrire. Ce dernier est de loin le plus rapide. Ou plutôt, le premier est lent.

Test sur banc

Premier

gem install benchmark_driver

Ensuite, installez benchmark_driver et installez-le.

square.yaml


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

Préparez un fichier YAML appelé

benchmark-driver square.yaml

Vous pouvez le comparer avec.

Mesuré avec ruby 2.7.1p83 (2020-03-31 révision a0c7c23c9c) [x86_64-darwin17], les résultats sont les suivants.

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

Hou la la!

Eh bien, même si c'est lent, il peut être exécuté 15 millions de fois par seconde, donc cette lenteur n'est un problème que lorsqu'on fait beaucoup de calculs numériques [^ sp].

[^ sp]: Lorsque vous souhaitez accélérer un programme, il est important de bien suivre les chiffres en effectuant un test de référence, et il est inutile d'élever la lignée pour optimiser la partie qui n'affecte pas le temps d'exécution de l'ensemble du programme. Je veux garder à l'esprit.

Amélioré avec Ruby 3.0

Des modifications ont été apportées pour traiter «** 2» spécialement pour Float et calculer plus rapidement. Vous pouvez le vérifier avec Ruby 3.0.0-preview1.

Si vous avez Ruby dans rbenv, vous pouvez facilement le tester avec benchmark_driver. Pour le même fichier YAML qu'avant, cette fois

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

Et. Les résultats sont les suivants.

                       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», plutôt «3.0.0-preview1» est plus lent, mais c'est dans la plage d'erreur. «x ** 2» est 2,3 fois plus rapide.

Impressions

Eh bien, x * x est toujours plus de deux fois plus rapide que x ** 2, mais je pense que c'est toujours une évolution importante. Il y a beaucoup de codes comme «x ** 2» et ils le rendent plus rapide sans rien faire.

Dans certains cas, vous voudrez peut-être utiliser «** 2» au détriment de la vitesse. C'est à ce moment que l'expression que vous souhaitez mettre au carré n'est pas dans la variable. Eh bien, ce genre d'image:

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

cette

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

Non seulement c'est redondant, mais cela le ralentit probablement. Donc, une fois que vous mettez la valeur de l'expression dans une variable

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

Sera écrit. Si la vitesse est la priorité la plus élevée, je l'écrirais comme ceci, mais si vous dites «Je veux de la vitesse mais je veux aussi de la simplicité», je pourrais utiliser «** 2».

Recommended Posts

Ruby 3.0 rend x ** 2 plus rapide
Liste de gemmes pour chaque version Ruby 2.5.x
[Java] Rendez le programme 10 fois plus rapide avec parallelStream
Construction de l'environnement CentOS8.2 (x86_64) + ruby2.5 + Rails5.2 + MariaDB (10.3.17)