web-dev-qa-db-fra.com

Le double est-il plus rapide que le float?

Les valeurs doubles stockent une précision plus élevée et font deux fois la taille d'un flotteur, mais les processeurs Intel sont-ils optimisés pour les flotteurs?

Autrement dit, les opérations doubles sont-elles aussi rapides ou plus rapides que les opérations flottantes pour +, -, * et /?

La réponse change-t-elle pour les architectures 64 bits?

65
Brent Faust

Il n'y a pas un seul "processeur Intel", surtout en ce qui concerne les opérations optimisées par rapport aux autres!, Mais la plupart d'entre elles, au niveau du processeur (en particulier dans le FPU), sont telles que la réponse à votre question:

les opérations doubles sont-elles aussi rapides ou plus rapides que les opérations flottantes pour +, -, * et /?

est "oui" - dans le CPU , sauf pour la division et sqrt qui sont n peu plus lent pour double que pour float . (En supposant que votre compilateur utilise SSE2 pour scalaire FP math, comme tous les compilateurs x86-64, et certains compilateurs 32 bits selon les options. Le x87 hérité n'a pas de largeurs différentes dans les registres, seulement en mémoire (il convertit en charge/stockage), donc historiquement, même sqrt et division étaient tout aussi lents pour double).

Par exemple, Haswell a un débit divsd de un par 8 à 14 cycles (dépendant des données), mais un débit divss (scalaire unique) de un par 7 cycles. x87 fdiv est un débit de 8 à 18 cycles. (Numéros de https://agner.org/optimize/ . La latence est en corrélation avec le débit pour la division, mais est supérieure aux nombres de débit.)

Les versions float de nombreuses fonctions de bibliothèque comme logf(float) et sinf(float) seront également plus rapides que log(double) et sin(double), car ils ont beaucoup moins de bits de précision pour bien faire les choses. Ils peuvent utiliser des approximations polynomiales avec moins de termes pour obtenir une précision totale pour float vs double


Cependant, occuper deux fois la mémoire pour chaque nombre implique clairement une charge plus lourde sur le (s) cache (s) et plus de bande passante mémoire pour remplir et renverser ces lignes de cache de/vers la RAM; le temps que vous vous souciez des performances d'une opération à virgule flottante est lorsque vous effectuez un lot de telles opérations, donc les considérations de mémoire et de cache sont cruciales .

@ La réponse de Richard souligne qu'il existe également d'autres façons d'effectuer les opérations FP (les instructions SSE /SSE2; bon vieux MMX était uniquement des entiers), particulièrement adapté aux opérations simples sur un grand nombre de données ("SIMD", instruction unique/données multiples) où chaque registre vectoriel peut contenir 4 flotteurs simple précision ou seulement 2 ceux à double précision , donc cet effet sera encore plus marqué.

En fin de compte, vous devez faire un benchmark, mais ma prédiction est que pour des benchmarks raisonnables (c'est-à-dire large ;-), vous trouverez l'avantage de coller avec une seule précision (en supposant bien sûr que vous n'avez pas besoin des bits de précision supplémentaires! -).

72
Alex Martelli

Si tous les calculs en virgule flottante sont effectués dans le FPU, alors, non, il n'y a pas de différence entre un calcul double et un calcul float car les opérations en virgule flottante sont en fait effectuées avec 80 bits de précision dans la pile FPU. Les entrées de la pile FPU sont arrondies selon les besoins pour convertir le format à virgule flottante 80 bits au format double ou float à virgule flottante. Le déplacement de sizeof(double) octets vers/depuis RAM contre sizeof(float) octets est la seule différence de vitesse.

Si, toutefois, vous disposez d'un calcul vectorisable, vous pouvez utiliser les extensions SSE pour exécuter quatre calculs float en même temps que deux calculs double. Par conséquent, une utilisation intelligente des instructions SSE et des registres XMM peut permettre un débit plus élevé sur les calculs qui utilisent uniquement floats.

24
Daniel Trebbien

Un autre point à considérer est si vous utilisez un GPU (la carte graphique). Je travaille avec un projet qui est numériquement intensif, pourtant nous n'avons pas besoin de la percision que double l'offre. Nous utilisons des cartes GPU pour accélérer encore le traitement. Les GPU CUDA ont besoin d'un package spécial pour prendre en charge le double, et la quantité de RAM sur un GPU est assez rapide, mais assez rare. En conséquence, l'utilisation de float double également la quantité de données que nous pouvons stocker sur le GPU.

Un autre point encore est la mémoire. Les flotteurs prennent moitié moins RAM en double. Si vous traitez avec de TRÈS grands ensembles de données, cela peut être un facteur très important. Si l'utilisation de double signifie que vous devez mettre en cache sur disque vs RAM pur, votre la différence sera énorme.

Donc, pour l'application avec laquelle je travaille, la différence est assez importante.

11
Miley

Je veux juste ajouter aux bonnes réponses déjà existantes que le __m256? famille de même-instruction-multiple-data ( SIMD ) Les fonctions intrinsèques C++ fonctionnent sur soit 4 double s en parallèle (par exemple _mm256_add_pd), ou 8 floats en parallèle (par exemple _mm256_add_ps).

Je ne sais pas si cela peut se traduire par une accélération réelle, mais il semble possible de traiter 2x autant de flottants par instruction lorsque SIMD est utilisé.

10
bobobobo

Dans les expériences d'ajout de 3,3 pour 2000000000 fois, les résultats sont les suivants:

Summation time in s: 2.82 summed value: 6.71089e+07 // float
Summation time in s: 2.78585 summed value: 6.6e+09 // double
Summation time in s: 2.76812 summed value: 6.6e+09 // long double

Donc double est plus rapide et par défaut en C et C++. Il est plus portable et par défaut dans toutes les fonctions de bibliothèque C et C++. Alos double a une précision significativement plus élevée que float.

Même Stroustrup recommande un flotteur double:

"La signification exacte de la précision simple, double et étendue est définie par l'implémentation. Choisir la bonne précision pour un problème où le choix importe nécessite une compréhension significative du calcul en virgule flottante. Si vous ne disposez pas de cette compréhension, obtenez des conseils, prenez le temps d'apprendre ou utilisez le double et espérez le meilleur. "

Peut-être que le seul cas où vous devriez utiliser float au lieu de double est sur du matériel 64 bits avec un gcc moderne. Parce que le flotteur est plus petit; double est de 8 octets et float de 4 octets.

9
Akash Agrawal

La seule réponse vraiment utile est: vous seul pouvez le dire. Vous devez comparer vos scénarios. De petits changements dans les modes d'instruction et de mémoire pourraient avoir un impact significatif.

Cela importera certainement si vous utilisez le FPU ou le matériel de type SSE (l'ancien fait tout son travail avec une précision étendue de 80 bits, donc le double sera plus proche; plus tard est nativement 32 bits, c'est-à-dire flottant).

Mise à jour: s/MMX/SSE/comme indiqué dans une autre réponse.

7
Richard

Le point flottant est normalement une extension de son processeur à usage général. La vitesse dépendra donc de la plateforme matérielle utilisée. Si la plate-forme prend en charge la virgule flottante, je serai surpris s'il y a une différence.

2
doron