Flottant, double ou les deux pour la classe Vector 2D?

11

J'écris actuellement un petit moteur de jeu 2D multiplateforme basé sur OpenGL pour notre studio. Lorsque j'ai recherché la classe de vecteur 2D à utiliser, je suis tombé sur trois paradigmes de conception différents:

  • Float & Call-by-value, comme dans cet article Gamasutra . Semble être rapide mais offre peu de précision (voir aussi ce fil ). Pro: rapide, portable et compatible avec la plupart des bibliothèques.

  • Double et appel par référence. Si je comprends bien l'article ci-dessus, je pourrais également utiliser 2 variables de double précision au lieu des 4 nombres flottants. Selon le fil ci-dessus, le double est toujours plus lent que le flotteur.

  • Modèle pour double et float: Le livre très populaire " Game Engine Architecture " utilise des modèles pour permettre d'utiliser float et double selon les besoins. L'inconvénient évident est le ballonnement du code. De plus, je doute que le code puisse être optimisé sans écrire fondamentalement deux classes, de toute façon.

J'apprécierais de savoir quelles solutions vous utilisez dans vos moteurs internes et la précision, par exemple, des moteurs de jeux populaires, afin que je puisse décider quelle solution je vais implémenter dans notre moteur. En ce moment, je pense simplement à utiliser la précision flottante et à vivre avec.

martinpi
la source
Plus lent ? Vous ne pouvez pas parler de vitesse si elle n'est pas liée à une architecture particulière.
o0 '.
2
@ Lo'oris: Je ne connais aucune architecture où le double est plus rapide que le float.
Plutôt que d'écrire votre propre classe de vecteur, pensez à utiliser celle de Sony ( bulletphysics.org/Bullet/phpBB3/… ). Il s'agit d'une "bibliothèque" simple d'en-tête, qui a déjà été micro-optimisée, et toutes les bibliothèques vectorielles sont de toute façon la même interface externe.
@Joe: 2 doubles au lieu de 4 flotteurs?
o0 '.
@ Lo'oris: La question est libellée un peu bizarre, je ne sais pas si l'interrogateur est confus ou juste vous - vous utilisez deux doubles "au lieu de" quatre flotteurs lorsque vous traitez avec SIMD, car le registre est de 128 bits de large. Vous devez toujours traiter un nombre égal de nombres, et vous le faites à mi-vitesse.

Réponses:

9

J'utilise toujours float sauf si j'ai une raison d'utiliser double, tout comme j'utilise int sauf si j'ai une raison d'utiliser int64_t.

Les flotteurs n'ont aucun problème à effectuer une arithmétique entière précise jusqu'à 2 24 , ce dont la plupart des gens ont peur (principalement de manière irrationnelle). Les doublons ne résolvent pas exactement le problème des valeurs communes qui ne peuvent pas être représentées exactement - que vous obteniez 0.10000001 ou 0.10000000000000001, vous devez toujours vous assurer que votre code le considère "égal" à 0,09999999.

Les doublons sont plus lents sur chaque plate-forme dont vous vous souciez pour l'écriture de jeux, prennent deux fois plus de bande passante mémoire et disposent de moins d'instructions CPU spécialisées.

Les flotteurs simple précision restent la norme pour les interfaces graphiques matérielles, à la fois côté C / C ++ et à l'intérieur des shaders.

Vous aurez probablement besoin d'un double vecteur à un moment donné, mais il devrait être utilisé en cas de besoin, pas par défaut.

En ce qui concerne les modèles - vous avez raison, pour des performances maximales, vous voudrez de toute façon spécialiser les modèles manuellement. En plus de cela, j'ai effectué des tests pour du code basé sur des modèles au cours du week-end (en créant un IntRect et un FloatRect à 4 éléments), et j'ai constaté que la version basée sur des modèles prenait environ 20 fois plus de temps à compiler que de simplement répéter le code, ce qui équivalait à environ 15 lignes. . La répétition craint, mais attendre les compilations est plus lourd - et ce n'est pas comme si j'allais avoir besoin d'un StringRect ou d'un FooRect.


la source
"Les doubles sont plus lents sur chaque plate-forme […] " - Citation nécessaire.
zénith
3

Le cadre de jeu Microsoft XNA a une classe Vector2 qui utilise des flottants. Ce serait ma principale raison personnelle d'aller avec des flotteurs, car j'ai confiance que la sagesse et l'expérience de l'équipe XNA sont bien plus grandes que les miennes.

J'ai trouvé assez intéressant de lire la réponse dans cette question de débordement de pile: "Float vs Double Performance" . Il y a aussi un fil gamedev.net avec une discussion sur la double performance dans les GPU. Je pense qu'il est prudent de supposer que les doubles sont plus lents que les flottants, du moins dans de nombreux GPU, et personnellement, j'ai toujours utilisé les fonctions OpenGL flottantes par rapport à leurs homologues doubles. Cela ne s'applique peut-être pas de nos jours, mais si vous considérez que tous ceux qui gèrent votre jeu n'ont pas le dernier GPU avec double support natif, je pense que c'est une raison suffisante pour utiliser des flotteurs et gagner un peu plus de performances.

Ricket
la source
1
De la question SO: "Sur les processeurs x86, au moins, float et double seront chacun convertis en un réel de 10 octets par le FPU pour le traitement." Bien que cela soit vrai, il néglige à la fois les instructions SIMD et les besoins en mémoire supplémentaire (= pire cohérence du cache, plus de bande passante mémoire) des doubles, qui continuent tous les deux à être plus lents qu'à flotter dans les tests du monde réel.
J'ai pensé qu'il y avait un hic. Vous devriez commenter cela sur la réponse SO, je voterais pour.
Ricket
Il est déjà là en tant que commentaire.
1
Depuis que vous avez introduit XNA, je peux aussi souligner que Direct2D utilise également des flottants simple précision.
Mike Strobel
Et pour être complet, OpenGL a des versions flottantes et doubles de ses méthodes, il est donc neutre dans ce sens.
Ricket