web-dev-qa-db-fra.com

Pourquoi les flotteurs font-ils toujours partie du langage Java alors que les doubles sont généralement recommandés à la place?

Dans tous les endroits que j'ai consultés, il est dit que double est supérieur à float dans presque tous les sens. float a été rendu obsolète par double en Java, alors pourquoi est-il toujours utilisé?

Je programme beaucoup avec Libgdx, et ils vous obligent à utiliser float (deltaTime, etc.), mais il me semble que double est juste plus facile à travailler en termes de stockage et de mémoire .

J'ai aussi lu Quand utilisez-vous float et quand utilisez-vous double , mais si float n'est vraiment bon que pour les nombres avec beaucoup de chiffres après la virgule, alors pourquoi peut-il ' t nous utilisons simplement l'une des nombreuses variantes de double?

Y a-t-il une raison pour laquelle les gens insistent pour utiliser des flotteurs même si cela n'a plus vraiment d'avantages? Est-ce simplement trop de travail pour tout changer?

84
Eames

LibGDX est un framework principalement utilisé pour le développement de jeux.

Dans le développement de jeux, vous devez généralement faire beaucoup de calculs en temps réel et toutes les performances que vous pouvez obtenir sont importantes. C'est pourquoi les développeurs de jeux utilisent généralement float chaque fois que la précision de float est suffisante.

La taille des registres FPU dans le CPU n'est pas la seule chose que vous devez considérer dans ce cas. En fait, la plupart des gros calculs dans le développement de jeux sont effectués par le GPU, et les GPU sont généralement optimisés pour les flottants, pas les doubles .

Et puis il y a aussi:

  • bande passante du bus mémoire (à quelle vitesse pouvez-vous pelleter des données entre RAM, CPU et GPU)
  • Cache CPU (ce qui rend le précédent moins nécessaire)
  • RAM
  • VRAM

qui sont toutes des ressources précieuses dont vous obtenez deux fois plus lorsque vous utilisez un flottant 32 bits au lieu d'un double 64 bits.

169
Philipp

Les flotteurs utilisent moitié moins de mémoire que les doubles.

Ils peuvent avoir moins de précision que les doubles, mais de nombreuses applications ne nécessitent pas de précision. Ils ont une plage plus large que tout format à virgule fixe de taille similaire. Par conséquent, ils remplissent un créneau qui a besoin de larges plages de nombres mais qui n'a pas besoin d'une grande précision et où l'utilisation de la mémoire est importante. Je les ai utilisés par le passé pour de grands réseaux de neurones, par exemple.

En dehors de Java, ils sont également largement utilisés dans les graphiques 3D, car de nombreux GPU les utilisent comme format principal - en dehors des périphériques NVIDIA Tesla/AMD FirePro très chers, la virgule flottante double précision est très lente sur les GPU.

57
Jules

Rétrocompatibilité

C'est la raison numéro un pour conserver le comportement dans un déjà existant langage/bibliothèque/ ISA /etc.

Considérez ce qui se passerait s'ils retiraient des flotteurs de Java. Libgdx (et des milliers d'autres bibliothèques et programmes) ne fonctionneraient pas. Il faudra beaucoup d'efforts pour que tout soit mis à jour, peut-être des années pour de nombreux projets (regardez simplement la compatibilité ascendante Python 2 à Python Et tout ne sera pas mis à jour, certaines choses seront cassées pour toujours parce que les responsables les ont abandonnées, peut-être plus tôt qu'elles n'auraient dû, car cela demanderait plus d'efforts qu'elles ne le souhaitent, ou parce que ce n'est plus possible pour accomplir ce que leur logiciel était censé faire.

Performance

Les doubles 64 bits prennent deux fois plus de mémoire et sont presque toujours plus lents à traiter que les flottants 32 bits (les très rares exceptions étant où la capacité de flottement 32 bits devrait être utilisée si rarement ou pas du tout, qu'aucun effort n'a été fait pour l'optimiser pour eux À moins que vous ne développiez pour du matériel spécialisé, vous ne le vivrez pas dans un avenir proche.)

Particulièrement pertinent pour vous, Libgdx est une bibliothèque de jeux. Les jeux ont tendance à être plus sensibles aux performances que la plupart des logiciels. Et les cartes graphiques de jeu (c'est-à-dire AMD Radeon et NVIDIA Geforce, pas FirePro ou Quadro) ont tendance à avoir des performances en virgule flottante 64 bits très faibles. Avec l'aimable autorisation d'Anandtech, voici comment les performances en double précision se comparent aux performances en simple précision sur certaines des meilleures cartes de jeu disponibles sur AMD's et NVIDIA (début 2016)

AMD
Card    R9 Fury X      R9 Fury       R9 290X    R9 290
FP64    1/16           1/16          1/8        1/8

NVIDIA
Card    GTX Titan X    GTX 980 Ti    GTX 980    GTX 780 Ti
FP64    1/32           1/32          1/32       1/24

Notez que les séries R9 Fury et GTX 900 sont plus récentes que les séries R9 200 et GTX 700, donc les performances relatives pour les virgules flottantes 64 bits diminuent. Remontez assez loin et vous trouverez la GTX 580, qui avait un rapport 1/8 comme la série R9 200.

1/32 de la performance est une assez grosse pénalité à payer si vous avez une contrainte de temps serrée et que vous ne gagnez pas beaucoup en utilisant le double plus grand.

48
8bittree

Opérations atomiques

En plus de ce que d'autres ont déjà dit, un inconvénient spécifique à Java de double (et long) est que les affectations aux types primitifs 64 bits ne sont pas garanties d'être atomique . À partir de Java Language Specification, Java SE 8 Edition , page 660 (non souligné dans l'original):

17.7 Traitement non atomique de double et long

Pour les besoins du modèle de mémoire du langage de programmation Java Java, une seule écriture sur une valeur non volatile long ou double est traitée comme deux écritures distinctes: une à chaque moitié de 32 bits. Cela peut entraîner une situation où un thread voit les 32 premiers bits d'une valeur de 64 bits à partir d'une écriture, et les 32 bits suivants d'une autre écriture.

Beurk.

Pour éviter cela, vous devez déclarer la variable 64 bits avec le mot clé volatile , ou utiliser une autre forme de synchronisation autour des affectations.

36
Kevin J. Chase

Il semble que d'autres réponses aient manqué un point important: les architectures SIMD peuvent traiter moins/plus de données selon qu'elles fonctionnent sur double ou float structs (par exemple, huit valeurs flottantes à la fois, ou quatre valeurs doubles à la fois).

Résumé des considérations de performances

  • float peut être plus rapide sur certains processeurs (par exemple, certains appareils mobiles).
  • float utilise moins de mémoire, donc dans les ensembles de données volumineux, il peut réduire considérablement la mémoire totale requise (disque dur/RAM) et la bande passante consommée.
  • float peut amener un processeur à consommer moins d'énergie (je ne trouve pas de référence, mais si cela n'est pas possible du moins semble plausible) pour les calculs en simple précision par rapport aux calculs en double précision.
  • float consomme moins de bande passante, et dans certaines applications, cela compte.
  • Les architectures SIMD peuvent traiter jusqu'à deux fois la même quantité de données car généralement.
  • float utilise autant que la moitié de la mémoire cache par rapport au double.

Résumé des considérations de précision

  • Dans de nombreuses applications, float suffit
  • double a de toute façon beaucoup plus de précision

Considérations de compatibilité

  • Si vos données doivent être soumises à un GPU (par exemple, pour un jeu vidéo utilisant OpenGL ou toute autre API de rendu), le format à virgule flottante est considérablement plus rapide que double (c'est-à-dire parce que les fabricants de GPU essaient d'augmenter le nombre de cœurs graphiques, et donc ils essaient d'économiser autant de circuits que possible dans chaque cœur, donc l'optimisation pour float permet de créer des GPU avec plus de cœurs à l'intérieur)
  • Les anciens GPU et certains appareils mobiles ne peuvent tout simplement pas accepter double comme format interne (pour les opérations de rendu 3D)

Conseils généraux

  • Sur les processeurs de bureau modernes (et probablement une bonne quantité de processeurs mobiles), vous pouvez essentiellement supposer que l'utilisation de variables temporaires double sur la pile donne une précision supplémentaire gratuite (précision supplémentaire sans perte de performances).
  • N'utilisez jamais plus de précision que nécessaire (vous ne savez peut-être pas de quelle précision vous avez réellement besoin).
  • Parfois, vous êtes juste forcé par la plage de valeurs (certaines valeurs seraient infinies si vous utilisez float, mais peuvent être des valeurs limitées si vous utilisez double)
  • Utiliser uniquement float ou seulement double aide grandement le compilateur à SIMD-ify les instructions.

Voir les commentaires ci-dessous de PeterCordes pour plus d'informations.

3
CoffeDeveloper

Outre les autres raisons évoquées:

Si vous avez des données de mesure, que ce soit des pressions, des débits, des courants, des tensions ou autre, cela se fait souvent avec du matériel ayant un ADC.

Un ADC a généralement 10 ou 12 bits, ceux de 14 ou 16 bits sont plus rares. Mais restons sur le 16 bits - si vous mesurez à pleine échelle, vous avez une précision de 1/65535. Cela signifie qu'un changement de 65534/65535 à 65535/65535 n'est que cette étape - 1/65535. C'est à peu près 1.5E-05. La précision d'un flotteur est d'environ 1E-07, donc beaucoup mieux. Cela signifie que vous ne perdez rien en utilisant float pour stocker ces données.

Si vous effectuez des calculs excessifs avec des flottants, vous effectuez légèrement moins bien qu'avec doubles en termes de précision, mais souvent vous n'avez pas besoin de cette précision, car vous ne vous souciez souvent pas si vous venez de mesurer une tension de 2 V ou 2.00002 V. De même, si vous convertissez cette tension en pression, peu vous importe si vous avez 3 bar ou 3.00003 bar.

0
glglgl