Pourquoi tant de développeurs pensent-ils que la performance, la lisibilité et la maintenabilité ne peuvent pas coexister?


34

En répondant à cette question , j'ai commencé à me demander pourquoi autant de développeurs pensent qu'un bon design ne doit pas rendre compte des performances, car cela affecterait la lisibilité et / ou la maintenabilité.

Je crois qu'un bon design prend également en compte les performances au moment de sa rédaction et qu'un bon développeur avec un bon design peut écrire un programme efficace sans nuire à la lisibilité ou à la maintenabilité.

Bien que je reconnaisse qu'il existe des cas extrêmes, pourquoi de nombreux développeurs insistent-ils sur le fait qu'un programme / design efficace conduira à une mauvaise lisibilité et / ou à une maintenabilité médiocre, et par conséquent que la performance ne devrait pas être une considération de conception?


9
Il serait presque impossible de raisonner à grande échelle, mais pour de petits morceaux de code, c'est assez évident. Il suffit de comparer les versions lisible et efficace de, par exemple, quicksort.
SK-logic le

7
Mu. Vous devriez commencer par appuyer votre affirmation selon laquelle de nombreux développeurs insistent sur le fait que l'efficacité conduit à une immobilité.
Peter Taylor

2
SK-logic: À mon avis, il s’agit de l’un des meilleurs atouts de tous les sites stackexchange, dans la mesure où l’on pose la question évidente, qui peut être saine de temps en temps. Ce qui pourrait être évident pour vous pourrait ne pas l'être pour quelqu'un d'autre, et inversement. :) Partager c'est aimer.
Andreas Johansson le

2
@Justin, non. Ce fil me semble présupposer une situation dans laquelle il y a un choix forcé entre un code efficace et un code maintenable. Le questionneur ne dit pas à quelle fréquence il se retrouve dans cette situation, et les répondeurs ne semblent pas prétendre être dans cette situation fréquemment.
Peter Taylor

2
-1 pour la question. Quand je l'ai lu, j'ai pensé que c'était un homme de paille et qu'il fallait expulser la seule réponse vraie: "Parce qu'ils n'utilisent pas de python."
Ingo

Réponses:


38

Je pense que de tels points de vue sont généralement des réactions à des tentatives d'optimisation prématurée (micro) , qui sont encore courantes et font généralement plus de mal que de bien. Quand on essaie de contrer de tels points de vue, il est facile de tomber - ou du moins de ressembler à - l'autre extrême.

Il est néanmoins vrai qu'avec le développement énorme des ressources matérielles au cours des dernières décennies, pour la plupart des programmes écrits aujourd'hui, les performances ont cessé d'être un facteur limitant majeur. Bien entendu, il convient de prendre en compte les performances attendues et réalisables au cours de la phase de conception, afin d' identifier les cas où les performances peuvent être (ou être) un problème majeur . Et puis, il est en effet important de concevoir pour la performance dès le début. Cependant, la simplicité, la lisibilité et la facilité de maintenance sont toujours plus importantes . Comme d'autres l'ont noté, le code à performances optimisées est plus complexe, plus difficile à lire et à gérer, et plus sujet aux bogues que la solution la plus simple. Ainsi, tout effort d’optimisation doit être prouvé - et pas seulement cru- apporter de réels avantages, tout en réduisant le moins possible la maintenabilité à long terme du programme. Ainsi, une bonne conception isole les parties complexes, exigeantes en performances, du reste du code , qui reste aussi simple et propre que possible.


8
"Quand on essaie de contrer de tels points de vue, il est facile de tomber - ou du moins de ressembler - à l'autre extrême" J'ai toujours des problèmes avec des gens qui pensent que je partage le point de vue opposé alors que je me contente de faire le bilan les inconvénients. Pas seulement dans la programmation, dans tout.
route le

1
J'en ai tellement marre de tous ceux qui discutent de ça que je me mets en colère et que je prends des extrêmes.
Thomas Bonini

Il y a eu plusieurs bonnes réponses, mais je pense que la vôtre a fait la meilleure tentative pour détailler les origines de cette mentalité. Merci à toutes les personnes impliquées!
Justin

Ma réponse ... la plupart des développeurs sont mauvais dans leur travail
TheCatWhisperer 12/12/17

38

Si vous répondez à votre question du côté d’un développeur qui travaille sur du code haute performance, plusieurs éléments doivent être pris en compte dans la conception.

  • Ne pas pessimiser prématurément. Lorsque vous avez le choix entre deux conceptions de complexité identique, choisissez celle qui présente les meilleures performances. L'un des exemples célèbres de C ++ est la prévalence de l'incrémentation postérieure de compteurs (ou itérateurs) dans les boucles. C'est une pessimisation prématurée totalement inutile qui ne PEUT rien vous coûter, mais ça PEUT, alors ne le faites pas.
  • Dans de nombreux cas, vous n'avez pas encore d'affaires pour vous rapprocher de la micro-optimisation. Les optimisations algorithmiques sont un fruit plus facile à comprendre et sont presque toujours beaucoup plus faciles à comprendre que les optimisations à très bas niveau.
  • Si et UNIQUEMENT si la performance est absolument critique, vous êtes sale et sale. En fait, vous isolez le code autant que vous le pouvez en premier, et ALORS vous vous retrouvez sale et sale. Et cela devient vraiment sale, avec des schémas de mise en cache, une évaluation paresseuse, une optimisation de la disposition de la mémoire pour la mise en cache, des blocs de composants intrinsèques ou d'assemblage en ligne, des modèles couche par couche, etc. Vous testez et documentez comme des fous blesser si vous devez effectuer une maintenance dans ce code, mais vous devez le faire car les performances sont absolument essentielles. Edit: En passant, je ne dis pas que ce code ne peut pas être beau, et il devrait être rendu aussi beau que possible, mais il sera quand même très complexe et souvent alambiqué par rapport à un code moins optimisé.

Faites-le bien, faites-le beau, faites-le vite. Dans cet ordre.


J'aime la règle de base: 'get it beautiful, get it fast. Dans cet ordre'. Je vais commencer à l'utiliser.
Martin York

Exactement. Et isolez le code dans le troisième point, autant que possible. Parce que lorsque vous passez à un matériel différent, même quelque chose d'aussi petit qu'un processeur avec une taille de cache différente, ces choses peuvent changer.
KeithB

@ KeithB - ​​vous faites valoir un bon point, je vais l'ajouter à ma réponse.
Joris Timmermans le

+1: "Fais-le bien, fais-le beau, fais vite. Dans cet ordre." Très beau résumé, avec lequel je suis d'accord à 90%. Parfois, je ne peux corriger que certains bugs (le corriger) une fois que je le trouve beau (et plus compréhensible).
Giorgio

+1 pour "Ne pas pessimiser prématurément". Le conseil pour éviter une optimisation prématurée n’est pas l’autorisation d’utiliser volontairement des algorithmes boneheaded. Si vous écrivez en Java et que vous avez une collection sur laquelle vous allez beaucoup appeler contains, utilisez un HashSet, pas un ArrayList. La performance n’importe peut-être pas, mais il n’ya aucune raison de ne pas le faire. Exploitez les congruences entre un bon design et de bonnes performances - si vous traitez une collection, essayez de tout faire en un seul passage, ce qui sera probablement à la fois plus lisible et plus rapide (probablement).
Tom Anderson

16

Si je peux prétendre "emprunter" le joli diagramme de @ greengit et faire un petit ajout:

|
P
E
R
F
O  *               X <- a program as first written
R   * 
M    *
A      *
N        *
C          *  *   *  *  *
E
|
O -- R E A D A B I L I T Y --

Nous avons tous été "appris" qu'il existe des courbes de compromis. En outre, nous avons tous supposé que nous étions des programmeurs tellement optimaux que tout programme donné que nous écrivons est si serré qu’il est sur la courbe . Si un programme est sur la courbe, toute amélioration dans une dimension entraîne nécessairement un coût dans l'autre dimension.

D'après mon expérience, les programmes ne s'approchent de la courbe qu'en ajustant, en peaufinant, en martelant, en cirant et en général en "code golf". La plupart des programmes offrent de nombreuses possibilités d'amélioration dans toutes les dimensions. Voici ce que je veux dire.


Personnellement, je pense qu’il ya une autre extrémité à la courbe où elle remonte à droite (tant que vous vous déplacez assez loin à droite (ce qui signifie probablement qu’il faut repenser votre algorithme)).
Martin York

2
+1 pour "La plupart des programmes ont encore beaucoup à faire dans toutes les dimensions."
Steven

5

Précisément parce que les composants logiciels hautement performants sont généralement des ordres de grandeur plus complexes que les autres composants logiciels (toutes choses étant égales par ailleurs).

Même dans ce cas, il n’est pas aussi clair que, si les métriques de performance sont une exigence cruciale, il est impératif que la conception présente une complexité qui permette de répondre à de telles exigences. Le danger est qu'un développeur gaspille un sprint sur une fonctionnalité relativement simple en essayant d'extraire quelques millisecondes supplémentaires de son composant.

Quoi qu'il en soit, la complexité de la conception a une corrélation directe avec la capacité d'un développeur à apprendre rapidement et à se familiariser avec une telle conception. De plus, de nouvelles modifications apportées aux fonctionnalités d'un composant complexe peuvent générer des bugs qui pourraient ne pas être détectés par les tests unitaires. Les conceptions complexes comportent de nombreuses autres facettes et scénarios de test possibles à envisager, ce qui rend l'objectif de couverture à 100% des tests unitaires encore plus réaliste.

Cela dit, il convient de noter qu’un composant logiciel peu performant pourrait ne pas fonctionner du simple fait qu’il était bêtement écrit et inutilement complexe sur la base de l’ignorance de l’auteur original (faire 8 appels de base de données pour créer une seule entité alors qu’un seul , code totalement inutile qui conduit à un seul chemin de code indépendamment de, etc ...) Ces cas sont davantage une question d’amélioration de la qualité du code et d’augmentations de performances dues au refactor et PAS à la conséquence attendue nécessairement.

Si un composant est bien conçu, il sera toujours moins complexe qu'un composant similaire conçu pour la performance (toutes choses étant égales par ailleurs).


3

Ce n'est pas tellement que ces choses ne peuvent pas coexister. Le problème est que le code de tout le monde est lent, illisible et impossible à maintenir à la première itération. Le reste du temps est consacré à l'amélioration de ce qui est le plus important. Si c'est la performance, alors allez-y. N'écrivez pas un code méchant, mais s'il doit simplement être rapide, faites-le vite. Je crois que performance et propreté ne sont fondamentalement pas corrélées. Le code performant ne provoque pas de code laid. Cependant, si vous passez votre temps à ajuster chaque morceau de code pour qu'il soit rapide, devinez ce que vous n'avez pas passé votre temps à faire? Rendre votre code propre et maintenable.


2
    |
    P
    E
    R
    F
    O *
    R * 
    M *
    UNE *
    N *
    C * * * * *
    E
    |
    O - LISIBILITE -

Comme vous pouvez le voir...

  • Le fait de sacrifier la lisibilité peut augmenter les performances, mais seulement dans de telles proportions. Après un certain point, vous devez recourir à des moyens "réels" tels que de meilleurs algorithmes et du meilleur matériel.
  • En outre, une perte de performance au détriment de la lisibilité ne peut se produire que dans une certaine mesure. Après cela, vous pouvez rendre votre programme aussi lisible que vous le souhaitez sans affecter les performances. Par exemple, ajouter plus de commentaires utiles ne nuit pas aux performances.

La performance et la lisibilité ne sont donc que faiblement liées - et dans la plupart des cas, il n’ya pas de véritables incitations préférant le premier au dernier. Et je parle ici de langues de haut niveau.


1

À mon avis, la performance devrait être prise en compte lorsqu'il s'agit d'un problème réel (ou, par exemple, d'une exigence). Si vous ne le faites pas, cela conduit à des microoptimisations, ce qui pourrait conduire à un code plus obscurci, ne serait-ce que pour économiser quelques microsecondes ici et là, ce qui conduirait à un code moins gérable et moins lisible. Au lieu de cela, il convient de se concentrer sur les véritables goulots d'étranglement du système, si nécessaire , et de mettre l'accent sur les performances.


1

Le problème n’est pas la lisibilité, mais l’efficacité. Si vous savez dès le départ que votre algorithme doit être hautement efficace, ce sera l'un des facteurs que vous utiliserez pour le développer.

La plupart des cas d'utilisation n'ont pas besoin d'un code ultra rapide. Dans de nombreux cas, les interactions IO ou utilisateur entraînent beaucoup plus de retard que l'exécution de votre algorithme. Le fait est que vous ne devriez pas faire tout votre possible pour rendre quelque chose de plus efficace si vous ne savez pas que c'est le goulot d'étranglement.

Optimiser le code pour améliorer les performances le rend souvent plus compliqué, car cela implique généralement de faire les choses de manière intelligente, au lieu des plus intuitives. Un code plus complexe est plus difficile à maintenir et plus difficile à récupérer pour les autres développeurs (les deux coûts sont à prendre en compte). Dans le même temps, les compilateurs sont très efficaces pour optimiser les cas courants. Il est possible que votre tentative d'améliorer un cas courant signifie que le compilateur ne reconnaît plus le modèle et ne peut donc pas vous aider à rendre votre code rapide. Il convient de noter que cela ne signifie pas écrire ce que vous voulez sans souci de performance. Vous ne devriez rien faire qui soit clairement inefficace.

Le but est de ne pas s'inquiéter de petites choses qui pourraient améliorer les choses. Utilisez un profileur et voyez que 1) ce que vous avez maintenant est un problème et 2) ce que vous avez changé en une amélioration.


1

Je pense que la plupart des programmeurs ont ce sentiment de base simplement parce que la plupart du temps, le code de performance est un code basé sur beaucoup plus d'informations (sur le contexte, la connaissance du matériel, l'architecture globale) que tout autre code dans les applications. La plupart du code n'exprimera que certaines solutions à des problèmes spécifiques encapsulés dans certaines abstractions de manière modulaire (comme des fonctions), ce qui implique de limiter la connaissance du contexte à ce qui entre dans cette encapsulation (comme les paramètres de fonction).

Lorsque vous écrivez pour obtenir de hautes performances, après avoir corrigé les optilisations algorithmiques, vous rentrez dans des détails qui nécessitent beaucoup plus de connaissances sur le contexte. Cela peut naturellement submerger tout programmeur qui ne se sent pas suffisamment concentré pour la tâche.


1

Parce que le coût du réchauffement climatique (à partir de ces cycles de calcul supplémentaires générés par des centaines de millions d'ordinateurs et de centres de données gigantesques) et la durée de vie médiocre de la batterie (sur les appareils mobiles de l'utilisateur), nécessaires pour exécuter leur code mal optimisé, sont rarement visibles sur la plupart des ordinateurs. les performances du programmeur ou les évaluations par les pairs.

C'est une externalité économique négative, semblable à une forme de pollution ignorée. Ainsi, le rapport coût / bénéfice de la réflexion sur la performance est mentalement biaisé par rapport à la réalité.

Les concepteurs de matériel ont travaillé d'arrache-pied en ajoutant des fonctions d'économie d'énergie et de mise à l'échelle d'horloge aux derniers processeurs. Il appartient aux programmeurs de laisser le matériel tirer parti de ces fonctionnalités plus souvent, en évitant d'induire en erreur chaque cycle d'horloge disponible.

AJOUT: De l’antiquité, le coût d’un ordinateur représentait des millions. L’optimisation du temps de calcul était donc très importante. Ensuite, le coût de développement et de maintenance du code est devenu supérieur à celui des ordinateurs, si bien que l’optimisation est tombée en désuétude par rapport à la productivité du programmeur. Aujourd'hui, toutefois, un autre coût devient supérieur au coût des ordinateurs: le coût d'alimentation et de refroidissement de tous ces centres de données devient maintenant supérieur au coût de tous les processeurs internes.


Outre la question de savoir si les ordinateurs ont contribué au réchauffement planétaire, même s’il était réel: c’est une erreur de dire que plus d’efficacité énergétique entraîne une réduction de la demande en énergie. Presque le contraire est vrai, comme on peut le voir dès le premier jour où un PC est apparu sur le marché. Auparavant, quelques centaines ou mille Mainframe (chacun équipé virtuellement de sa propre centrale) consommaient beaucoup moins d'énergie qu'aujourd'hui, où une minute de processeur calcule beaucoup plus qu'à une fraction du coût et de la demande en énergie. Pourtant, la demande totale en énergie pour l'informatique est plus élevée qu'avant.
Ingo

1

Je pense que c'est difficile d'atteindre tous les trois. Je pense que deux peuvent être réalisables. Par exemple, je pense qu'il est possible d'atteindre efficacité et lisibilité dans certains cas, mais la maintenabilité peut être difficile avec du code micro-réglé. Le plus efficace sur le code de la planète manquent souvent à la fois la maintenabilité et la lisibilité est probablement comme évident pour la plupart, à moins que vous êtes le genre qui peut comprendre la main-SoA vectorisé, multithread Code SIMD Intel écrit avec l' assemblage inline, ou le plus coupe Algorithmes novateurs utilisés dans l'industrie avec des articles mathématiques de 40 pages publiés il y a à peine 2 mois et 12 bibliothèques d'un code pour une structure de données incroyablement complexe.

Micro-efficacité

Une chose que je suggérerais qui pourrait être contraire à l’opinion populaire est que le code algorithmique le plus intelligent est souvent plus difficile à maintenir que l’algorithme simple le plus micro-réglé. Cette idée que les améliorations en matière d’évolutivité rapportent plus sur le code micro-ajusté (ex: schémas d’accès conviviaux pour le cache, multithreading, SIMD, etc.) est quelque chose que je contesterais, au moins après avoir travaillé dans un secteur extrêmement complexe. structures de données et algorithmes (l'industrie des effets visuels), en particulier dans des domaines tels que le traitement de maillage, parce que le bang est énorme, mais que le coût est extrêmement coûteux lorsque vous introduisez de nouveaux algorithmes et structures de données dont personne n'a jamais entendu parler depuis qu'ils sont de marque Nouveau. De plus, je '

Donc, cette idée que les optimisations algorithmiques ont toujours préséance sur, disons, les optimisations liées aux modèles d'accès à la mémoire est toujours quelque chose avec lequel je n'étais pas tout à fait d'accord. Bien sûr, si vous utilisez une sorte de bulle, aucune micro-optimisation ne peut vous aider… mais dans des limites raisonnables, je ne pense pas que ce soit toujours aussi net. Et on peut soutenir que les optimisations algorithmiques sont plus difficiles à maintenir que les micro-optimisations. Je trouve qu'il est beaucoup plus facile de maintenir, par exemple, Embree d'Intel, qui utilise un algorithme BVH classique et simple et en résout simplement le foutre que le code OpenVDB de Dreamwork pour des méthodes de pointe d'accélération algorithmique de la simulation fluide. Donc, au moins dans mon secteur d'activité, j'aimerais voir davantage de personnes familiarisées avec la micro-optimisation de l'architecture informatique, comme le faisait Intel lorsqu'elles sont entrées en scène, au lieu de proposer des milliers et des milliers de nouveaux algorithmes et structures de données. Avec des micro-optimisations efficaces, les utilisateurs pourraient potentiellement trouver de moins en moins de raisons d'inventer de nouveaux algorithmes.

Auparavant, je travaillais dans une base de code héritée, où presque chaque opération utilisateur possédait sa propre structure de données et son algorithme (ajoutant ainsi des centaines de structures de données exotiques). Et la plupart d’entre eux avaient des caractéristiques de performance très asymétriques, s’appliquant très étroitement. Cela aurait été tellement plus facile si le système pouvait s'articuler autour d'une vingtaine de structures de données plus largement applicables, et je pense que cela aurait pu être le cas si elles avaient été optimisées au niveau micro. Je parle de ce cas parce que la micro-optimisation peut potentiellement améliorer considérablement la maintenabilité dans un tel cas si cela signifie la différence entre des centaines de structures de données micro-pessimisées qui ne peuvent même pas être utilisées en toute sécurité à des fins strictes en lecture seule, ce qui implique des erreurs de cache en mémoire. droit vs.

Langages fonctionnels

Entre-temps, certains des codes les plus faciles à gérer que j'ai rencontrés étaient assez efficaces, mais extrêmement difficiles à lire, car ils étaient écrits dans des langages fonctionnels. En général, la lisibilité et la maintenabilité sont des idées contradictoires à mon avis.

Il est très difficile de rendre le code lisible, maintenable et efficace en même temps. En règle générale, vous devez faire un compromis sur l'un de ces trois, voire deux, comme compromettre la lisibilité pour la maintenabilité ou compromettre la maintenabilité pour l'efficacité. C’est généralement la facilité de maintenance qui en souffre lorsque vous recherchez beaucoup les deux autres.

Lisibilité contre maintenabilité

Maintenant, comme je l’ai dit, la lisibilité et la maintenabilité ne sont pas des concepts harmonieux. Après tout, le plus code lisible pour la plupart d' entre nous mortels cartes très intuitivement à des modèles pensée humaine, et les modèles de pensées humaines sont intrinsèquement sujettes à l' erreur: " . Dans ce cas, le faire si cela se produit, le faire faire autrement cette Oops.. J'ai oublié quelque chose! Si ces systèmes interagissent les uns avec les autres, cela devrait se produire pour que ce système puisse le faire ... oh, attendez, qu'en est-il de ce système lorsque cet événement est déclenché?"J'avais oublié la citation exacte, mais quelqu'un a dit un jour que si Rome était construite comme un logiciel, il suffirait qu'un oiseau se pose sur un mur pour le faire tomber. C'est le cas de la plupart des logiciels. C'est plus fragile que nous nous soucions souvent de Quelques lignes de code apparemment inoffensif ici et là pourraient bien nous permettre de revenir sur notre conception, et les langages de haut niveau visant à être aussi lisibles que possible ne font pas exception à de telles erreurs de conception. .

Les langages fonctionnels purs sont à peu près aussi invulnérables que possible (pas même invulnérables, mais relativement plus proches que la plupart des autres). Et c'est en partie parce qu'ils ne correspondent pas intuitivement à la pensée humaine. Ils ne sont pas lisibles. Ils nous imposent des schémas de pensée qui nous obligent à résoudre des problèmes avec le moins de cas spéciaux possible en utilisant le minimum de connaissances possible et sans provoquer d'effets secondaires. Ils sont extrêmement orthogonaux, ils permettent souvent de changer sans cesse le code, si surprenant que nous devons repenser la conception sur une planche à dessin, au point de changer d’avis sur la conception globale, sans avoir à tout réécrire. Cela ne semble pas être plus facile à gérer que ça ... mais le code est toujours très difficile à lire,


1
"Micro-efficacité", c'est un peu comme dire "Il n'y a pas d'accès mémoire O (1)."
Caleth

0

Un problème est que le temps fini imparti aux développeurs signifie que tout ce que vous cherchez à optimiser vous évite de passer du temps sur les autres problèmes.

Il existe une assez bonne expérience sur ce sujet référencé dans Code complet de Meyer. Différents groupes de développeurs ont été sollicités pour optimiser la vitesse, l'utilisation de la mémoire, la lisibilité, la robustesse, etc. Il a été constaté que leurs projets obtenaient de bons résultats dans tout ce qu’on leur demandait d’optimiser, mais moins bien dans toutes les autres qualités.


Évidemment, vous pouvez consacrer plus de temps, mais vous finissez par vous demander pourquoi les développeurs prennent du temps pour programmer l'amour d'Emacs afin d'exprimer leur amour pour leurs enfants. À ce stade, vous êtes fondamentalement Sheldon du Big Bang Theory
Deworde

0

Parce que les programmeurs expérimentés ont appris que c'était vrai.

Nous avons travaillé avec un code maigre et moyen, sans problèmes de performances.

Nous avons travaillé sur de nombreux codes qui, pour résoudre les problèmes de performances, sont TRÈS complexes.

Un exemple immédiat qui me vient à l’esprit est que mon dernier projet incluait 8 192 tables SQL partagées manuellement. Cela était nécessaire en raison de problèmes de performances. La configuration permettant de sélectionner une table est beaucoup plus simple que de sélectionner et de gérer 8 192 fragments.


0

Il existe également des morceaux célèbres de code hautement optimisé qui plieront le cerveau de la plupart des gens et qui soutiendront le fait que le code hautement optimisé est difficile à lire et à comprendre.

Voici le plus célèbre je pense. Extrait de Quake III Arena et attribué à John Carmak, bien que je pense qu'il y ait eu plusieurs itérations de cette fonction et qu'elle n'a pas été créée à l'origine par lui ( Wikipedia n'est-il pas génial? ).

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;
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.