Racine carrée inverse rapide

La racine carrée inverse rapide (en anglais fast inverse , parfois abrégé Fast InvSqrt() ou par la constante 0x5f3759df en hexadécimal) est une méthode pour calculer x−½, l'inverse de la racine carrée d'un nombre à virgule flottante à simple précision sur 32 bits. L'algorithme a probablement été développé chez Silicon Graphics au début des années 1990. Il a entre autres été 1 utilisé dans le code source de III Arena, un jeu vidéo sorti en 1999 . À l'époque, le principal avantage de cet algorithme était d'éviter d'utiliser des coûteuses opérations à virgules flottantes en préférant des opérations sur entiers. Les racines carrées inverses sont utilisées pour calculer les angles d'incidence et la réflexion pour la lumière et l'ombre en imagerie numérique.

L'algorithme prend en entrée des flottants de 32 bits non signés et stocke la moitié de cette valeur pour l'utiliser plus tard. Ensuite, il traite le nombre à virgule flottante comme un entier et lui applique un décalage logique (en) à droite d'un bit et le résultat est soustrait à la valeur « magique » 0x5f3759df. Il s'agit de la première approximation de la racine carrée inverse du nombre passé en entrée. En considérant de nouveau les bits comme un nombre à virgule flottante et en appliquant au nombre la méthode de Newton, on améliore Les calculs de lumière (ici cette approximation. Bien que n'assurant pas la précision la plus fine possible, le résultat final est une approximation de la racine dans OpenArena, un jeu de tir carrée inverse d'un nombre à virgule flottante qui s'exécute quatre fois plus vite qu'une division d'un tel nombre. à la première personne) utilisent la racine carrée inverse rapide pour calculer les angles d'incidence et de Sommaire réflexion.

1 Motivation 2 Aperçu du code 2.1 Un exemple pratique 3 Fonctionnement de l'algorithme 3.1 Représentation en nombre flottant 3.2 Approcher un logarithme en passant à l'entier 3.3 Première approximation du résultat 3.4 Méthode de Newton 4 Histoire et enquête 5 Note et références 6 Liens externes

Motivation

2 Les racines carrées inverses d'un nombre à virgule flottante sont utilisées pour calculer un vecteur normalisé . En synthèse d'image 3D, ces vecteurs normalisés sont utilisés pour déterminer l'éclairage et l'ombrage. Des millions de ces calculs sont ainsi nécessaires chaque seconde. Avant l'apparition de matériel dédié au TCL, ces calculs pouvaient être lents. Ce fut particulièrement le cas lorsque cette technique a été développée au début des années 1990 où les opérations sur les nombres à virgule flottante étaient plus lentes que 1 les calculs sur entiers .

Afin de normaliser un vecteur, on détermine la longueur de celui-ci en calculant sa norme euclidienne : la racine carrée de la somme du carré de ses composantes. Après avoir divisé chaque composante par cette longueur, on obtient alors un nouveau vecteur unitaire Les normales à une surface pointant dans la même direction. sont largement utilisées dans les calculs d'éclairage et d'ombrage, ce qui nécessite le est la norme euclidienne du vecteur, de la même manière que l'on calcule une distance dans un espace calcul des normes des vecteurs. Ici, on montre un euclidien. champ de vecteurs normaux à la surface. est le vecteur (unitaire) normalisé. Avec représentant ,

, liant le vecteur unitaire à la racine carrée inverse des composantes.

Aperçu du code

Le code source suivant est l'implémentation de la racine carrée inverse dans Quake III Arena dont on a retiré les directives du préprocesseur C mais qui contient les 3 commentaires originaux float Q_rsqrt( float number ) { long i; float x2, y; const float threehalfs = 1.5F;

x2 = number * 0.5F; y = number; i = * ( long * ) &y; // evil floating point bit level hacking i = 0x5f3759df - ( i >> 1 ); // what the fuck? y = * ( float * ) &i; y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed

return y; }

Afin de déterminer la racine carrée inverse, un programme calculerait une approximation de puis appliquerait ensuite une méthode numérique afin de peaufiner le résultat jusqu'à atteindre une erreur d'approximation acceptable. Des méthodes de calcul (en) du début des années 1990 ont permis d'avoir une première 4 approximation depuis une table de correspondance . Cette nouvelle fonction s'est montrée plus efficace que les tables de correspondance et environ quatre fois plus 5 6 rapide qu'une division flottante classique . L'algorithme a été conçu selon le standard pour les nombres à virgule flottante 32-bit, mais des recherches de Chris Lomont et ensuite Charles McEniry ont montré qu'il pouvait être implémenté en utilisant d'autres spécifications de nombres à virgule flottante. 7 Le gain de vitesse apporté par le kludge qu'est la racine carrée inverse rapide vient du traitement du mot double contenant le nombre à virgule flottante considéré comme entier qui est ensuite soustrait à une constante spécifique : 0x5f3759df. L'utilité de cette constante n'étant pas claire à première vue, on la considère alors 1, 8, 9, 10 comme un nombre magique Après cette soustraction d'entiers et ce décalage à droite on obtient un mot double qui, lorsqu'il est considéré comme un nombre à virgule flottante, devient une approximation grossière de la racine carrée inverse du nombre entré. Ensuite, une itération de la méthode de Newton est réalisée afin de gagner en précision et le résultat est retourné. L'algorithme génère des résultats raisonnablement précis en utilisant une seule approximation par la méthode de 11 Newton ; Toutefois, il reste plus lent que d'utiliser l'instruction SSE rsqrtss sortie elle aussi en 1999 sur les processeurs .

Un exemple pratique

Considérons un nombre x = 0,156 25, pour lequel on souhaite calculer 1/√ x ≈ 2,529 82. Voici les premières étapes de l'algorithme :

0011_1110_0010_0000_0000_0000_0000_0000 Trame binaire de x et i 0001_1111_0001_0000_0000_0000_0000_0000 Décalage à droite d'une position : (i >> 1) 0101_1111_0011_0111_0101_1001_1101_1111 Le nombre magique 0x5f3759df 0100_0000_0010_0111_0101_1001_1101_1111 le résultat de 0x5f3759df - (i >> 1)

En utilisant la représentation IEEE 32-bit :

0_01111100_01000000000000000000000 1.25 * 2^-3 0_00111110_00100000000000000000000 1.125 * 2^-65 0_10111110_01101110101100111011111 1.432430... * 2^+63 0_10000000_01001110101100111011111 1.307430... * 2^+1

En réinterprétant la dernière trame binaire en tant que nombre à virgule flottante on obtient l'approximation y = 2,614 86 ayant une erreur relative d'environ 3,4 %. Après une itération de la méthode de Newton, le résultat final est y = 2,525 49 avec une erreur de seulement 0,17 %.

Fonctionnement de l'algorithme

L'algorithme calcule 1/√ x en effectuant les étapes suivantes :

1. Transforme l'argument x en entier afin d'appliquer une approximation de log2(x) ; 2. Utilise cet entier pour calculer une approximation de log2(1/√ x) ; 3. Transforme celui-ci afin de revenir à un nombre flottant afin d'effectuer une approximation de l'exponentielle base-2 ; 4. Affine l'approximation en utilisant une itération de la méthode de Newton.

Représentation en nombre flottant

Puisque cet algorithme se base fortement sur la représentation bit à bit des nombres à virgule flottante de simple-précision, un aperçu rapide de ce système est fourni ici. Afin d'encoder un nombre réel non nul x en tant que flottant de simple-précision, on commence par écrire x comme un nombre binaire en notation scientifique :

Où l'exposant ex est un entier, mx ∈ [0, 1), et 1.b1b2b3... est la représentation binaire de la "mantisse" (1 + mx). Notons qu'il n'est pas nécessaire d'enregistrer le bit avant le point dans la mantisse car il vaut toujours 1. Avec ce formalisme, on calcule 3 entiers :

Sx, le "bit de signe", valant 0 si x > 0 ou 1 si x < 0 (1 bit) 12 Ex = ex + B est "l'exposant biaisé" où B = 127 est le "biais d'exposant" (en) (8 bits) 23 13 Mx = mx × L, où L = 2 (23 bits)

Ces valeurs sont ensuite condensées de gauche à droite dans un conteneur 32 bit.

Par exemple, en utilisant le nombre x = 0,156 25 = 0,001 012. En normalisant x on a :

Donc, les trois valeurs entières non signées sont : S = 0 E = −3 + 127 = 124 = 011111002 23 M = 0.25 × 2 = 2097152 = 010000000000000000000002

Ces champs sont condensés comme ceci :

Approcher un logarithme en passant à l'entier

S'il fallait calculer 1/√ x sans un ordinateur ou une calculatrice, une table de logarithmes serait utile accompagnée de l'identité logb(1/√ x) = −½ logb(x) valide quelle que soit la base b. La racine carrée inverse rapide repose sur cette dernière ainsi que sur le fait que l'on puisse effectuer un logarithme approximatif d'un nombre en passant d'un float32 à un entier. Explications :

Soit x un nombre positif :

On a alors

14 Mais puisque mx ∈ [0, 1), le logarithme de la partie droite peut être arrondi par

où σ est un paramètre arbitraire permettant de régler l'arrondi. Par exemple : σ = 0 fournit des résultats exacts aux bords de l'intervalle tandis que σ ≈ 0.0430357 fournit l'approximation optimale.

Alors nous avons l'approximation

15 D'un autre côté, en interprétant la représentation binaire de x en tant qu'entier, on obtient :

L'entier converti en nombre flottant (en bleu), comparé à On remarque alors que I est une approximation linéaire mise à l'échelle et décalée de log (x), comme présenté sur le graphique ci- x 2 un logarithme décalé et à contre. En d'autres termes, log2(x) est approché par l'échelle (en gris).

Première approximation du résultat

Le calcul de y = 1/√ x est basé sur l'identité

En utilisant l'approximation du logarithme telle que précédemment définie et appliquée à x et y, l'équation devient :

Qui s'écrit en code C : i = 0x5f3759df - ( i >> 1 );

Le premier terme étant le nombre magique

16 à partir duquel on déduit σ ≈ 0.0450466. Le second terme, ½ Ix est déterminé en décalant à droite une fois les bits de Ix .

Méthode de Newton

Après avoir appliqué ces opérations, l'algorithme considère de nouveau le mot double comme nombre flottant (y = *(float*)&i;) et effectue une multiplication en nombre flottant (y = y*(1.5f - xhalf*y*y);). Celle-ci étant une itération de la méthode de Newton permettant de trouver des solutions à une équation donnée. Pour ce même exemple :

est la racine carrée inverse, ou encore, en fonction de y :

.

Avec représentant l'expression générale de la méthode de Newton avec comme première approximation,

est l'expression particulière où et .

Ainsi y = y*(1.5f - xhalf*y*y); est semblable à

La première approximation est générée en utilisant les opérations en tant qu'entiers puis fournie aux deux dernières lignes de code de la fonction. Des itérations répétées de cet algorithme en utilisant la sortie de la fonction ( ) comme argument pour l'itération suivante fait converger l'algorithme sur la racine avec une 17 incertitude de plus en plus faible . Une seule itération a été utilisée dans le cadre du moteur de Quake III, une seconde itération ayant été commentée et laissée.

Histoire et enquête

Le code source de Quake III a été diffusé après la QuakeCon 2005, mais des copies de la racine carrée inverse rapide sont apparues 1 sur Usenet et d'autres forums dès 2002/2003 . Les spéculations à l'époque pointent comme auteur probable de la fonction. Mais ce dernier dément la chose et suggère que la fonction a été écrite par Terje Mathisen, un programmeur assembleur talentueux qui a assisté les développeurs d' pour optimiser Quake. Mathisen a effectivement écrit une fonction similaire à la fin des années 1990, mais les auteurs originaux remontent à plus loin dans l'histoire de l'infographie 3D avec l'implémentation faite par Gary Tarolli pour un SGI Indigo (en) qui serait l'une des premières utilisations connues. Rys Sommefeldt, auteur de l'enquête, finit par conclure que l'algorithme original est l'œuvre de Greg Walsh de Ardent Computer (en) en collaboration avec Cleve Moler, fondateur de 18 MathWorks. Cependant, aucune preuve concluante concernant l'auteur n'existe .

On ne sait pas comment la valeur exacte du nombre magique a été déterminée. Chris Lomont a développé une fonction pour minimiser l'erreur d'approximation en choisissant le nombre magique R dans un intervalle. Il calcule d'abord la constante optimale pour l'étape approximation linéaire, il obtient 0x5f37642f qui est proche de 0x5f3759df, mais avec cette nouvelle constante, il obtient une 19 précision moindre après une itération de la méthode de Newton . Il cherche alors une constante optimale même après une ou deux John Carmack, cofondateur itérations de la méthode de Newton et obtient la valeur 0x5f375a86 qui se révèle plus précise que l'originale, même après chaque 19 20 d'id Software, est souvent étape d'itération . Il conclut alors en se demandant si la valeur originale a été choisie par dérivation ou par essai-erreur . Dans la associé à cette fonction, lancée, Lomont indique aussi que la valeur magique pour flottant double précision 64-bits IEEE 754 est 0x5fe6ec85e7de30da, mais il 21 même s'il ne l'a pas écrite. a été démontré que la valeur exacte était 0x5fe6eb50c7b537a9 . Charles McEniry a effectué une optimisation similaire mais plus sophistiquée sur les valeurs probables pour R. Il cherche d'abord par une méthode par force brute et obtient la valeur déterminée par 22 Lomont . Il a ensuite essayé de rechercher cette valeur par une méthode de dichotomie et obtient alors la valeur utilisée initialement dans la fonction, ce qui conduit 23 McEniry à penser que cette constante a probablement été obtenue par cette méthode . Note et références

(en) Cet article est partiellement ou en totalité issu de l’article de Wikipédia en anglais intitulé « Fast inverse square root (https://en.wikipedia.org/wiki/Fast_inverse _square_root?oldid=508816170) » (voir la liste des auteurs (https://en.wikipedia.org/wiki/Fast_inverse_square_root?action=history)).

1. (en) Origin of Quake3's Fast InvSqrt() (http://www.beyond3d.com/content/articles/8/) Beyond3D.com, consulté le 16 septembre 2012. 2. (en) Jim Blinn, Jim Blinn's Corner: Notation, Notation, Notation, Morgan Kaufmann, 2003 (ISBN 978-1-55860-860-3, lire en ligne (http://books.google.fr/books?id=vEHb-8yWbG0C&pg= PA130)), p. 130 3. quake3-1.32b/code/game/q_math.c (ftp://ftp.idsoftware.com/idstuff/source/quake3-1.32b-source.zip) id Software consulté 16 septembre 2012 4. (en) David Eberly, 3D Game Engine Design, Morgan Kaufmann, 2001 (ISBN 978-1-55860-593-0), p. 504. 5. (en) Lomont Chris, « Fast Inverse Square Root » (http://www.lomont.org/Math/Papers/2003/InvSqrt.pdf), sur www.lomont.org,​ février 2003 (consulté le 13 février 2009), p. 1. 6. IEEE 754-1985 (en). 7. L'utilisation du type long réduit la portabilité de ce code sur les systèmes récents. Afin que le code s'exécute, sizeof(long) doit valoir 4 octets sinon la fonction risque de retourner des résultats négatifs. Sur les systèmes 64-bit récents, sizeof(long) vaut 8 octets. 8. (en) Lomont Chris, « Fast Inverse Square Root » (http://www.lomont.org/Math/Papers/2003/InvSqrt.pdf), sur www.lomont.org,​ février 2003 (consulté le 13 février 2009), p. 3. 9. (en) Charles McEniry, « The Mathematics Behind the Fast Inverse Square Root Function Code » (http://www.daxia.com/bibis/upload/406Fast_Inverse_Square_Root.pdf), sur daxia.com,​ août 2007 (consulté le 13 février 2009), p. 1. 10. (en) David Eberly, 3D Game Engine Design, Morgan Kaufmann, 2001 (ISBN 978-1-55860-593-0), p. 2. 11. (en) Elan Ruskin, « Timing Square Root » (http://assemblyrequired.crashworks.org/timing-square-root/), sur assemblyrequired.crashworks.org,​ 16 octobre 2009 (consulté le 7 mai 2015). 12. Ex doit être dans le domaine [1, 254] afin que x soit représentable comme un nombre normal (en) 13. Les seuls réels pouvant être représentés exactement comme des nombres à virgule flottante sont ceux pour lesquels Mx est un entier. Les autres nombres ne peuvent être représentés que de façon approchée en les arrondissant au nombre représentable le plus proche. 14. (en) Charles McEniry, « The Mathematics Behind the Fast Inverse Square Root Function Code » (http://www.daxia.com/bibis/upload/406Fast_Inverse_Square_Root.pdf), sur daxia.com,​ août 2007 (consulté le 13 février 2009), p. 3. 15. Sx = 0 puisque x > 0. 16. Hennessey & Patterson 1998, p. 305. 17. (en) Charles McEniry, « The Mathematics Behind the Fast Inverse Square Root Function Code » (http://www.daxia.com/bibis/upload/406Fast_Inverse_Square_Root.pdf), sur daxia.com,​ août 2007 (consulté le 13 février 2009), p. 6. 18. Origin of Quake3's Fast InvSqrt() - Part Two (http://www.beyond3d.com/content/articles/15/) Beyond3D.com, consulté le 17 septembre 2012. 19. Lomont 2003, p. 10. 20. Lomont 2003, p. 10–11. 21. (en) Matthew Robertson, « A Brief History of InvSqrt » (http://eggroll.unbsj.ca/rsqrt/rsqrt.pdf), UNBSJ,​ 24 avril 2012. 22. McEniry 2007, p. 11-12. 23. McEniry 2007, p. 16.

Liens externes

(en) A Brief History of InvSqrt (http://eggroll.unbsj.ca/rsqrt/rsqrt.pdf) par Matthew Robertson (en) Fast Inverse Square Root (http://www.lomont.org/Math/Papers/2003/InvSqrt.pdf) par Chris Lomont (en) Origin of Quake 3's Fast InvSqrt() (http://www.beyond3d.com/content/articles/8/) (en) Code source de Quake III Arena (http://www.idsoftware.com/business/techdownloads/)

Ce document provient de « https://fr.wikipedia.org/w/index.php?title=Racine_carrée_inverse_rapide&oldid=132819657 ».

Dernière modification de cette page le 18 décembre 2016, à 17:34. Droit d'auteur : les textes sont disponibles sous licence Creative Commons attribution, partage dans les mêmes conditions ; d’autres conditions peuvent s’appliquer. Voyez les conditions d’utilisation pour plus de détails, ainsi que les crédits graphiques. En cas de réutilisation des textes de cette page, voyez comment citer les auteurs et mentionner la licence. Wikipedia® est une marque déposée de la Wikimedia Foundation, Inc., organisation de bienfaisance régie par le paragraphe 501(c)(3) du code fiscal des États-Unis.