La Performance de types intégrés : char vs court vs int ou float vs double
Cela peut paraître un peu bête question mais en voyant Alexandre C répondre dans l'autre sujet, je suis curieux de savoir que si il n'y a aucune différence de performances avec les types intégrés:
char
vsshort
vsint
vsfloat
vsdouble
.
Habituellement, nous ne la considérons pas comme telle différence de performance (le cas échéant) dans notre vie réelle des projets, mais je voudrais savoir ce pour des fins éducatives. Questions d'ordre général qui peut être posée est la suivante:
-
Est-il une différence de performance entre intégrante de l'arithmétique et de l'arithmétique à virgule flottante?
-
Qui est le plus rapide? Quelle est la raison d'être plus rapide? Veuillez expliquer cela.
- De profil, et de les mesurer. Utiliser un très grand nombre d'itérations.
- Mathieu: Qui peut répondre à ma question : qui est plus rapide. Mais pas "pourquoi est-ce plus rapide".
- En Plus des cours, les types d'entiers et à virgule flottante types sont bons pour des choses très différentes. Je ne peux penser à quelques situations où je considère à la fois acceptable.
- Si vous êtes à la programmation d'un périphérique sans FPU alors il peut être intéressant de sacrifier la précision et le temps du programmeur pour convertir un algorithme de virgule flottante entier (avec les facteurs d'échelle).
Vous devez vous connecter pour publier un commentaire.
Float vs entier:
Historiquement, virgule flottante pourrait être beaucoup plus lent que l'arithmétique des nombres entiers. Sur les ordinateurs modernes, ce n'est plus vraiment le cas (il est un peu plus lent sur certaines plates-formes, mais à moins que vous écrivez parfait de code et de les optimiser pour chaque cycle, la différence sera submergé par les autres inefficacités dans votre code).
Sur quelque peu limitée processeurs, comme ceux dans le haut de gamme des téléphones cellulaires, à virgule flottante peut être un peu plus lent que entier, mais c'est généralement dans un ordre de grandeur (ou mieux), tant qu'il y a du matériel à virgule flottante disponible. Il est intéressant de noter que cet écart tend à se réduire assez rapidement que les téléphones cellulaires sont appelés à exécuter plus et, plus généralement, le calcul de la charge de travail.
Sur très limité de processeurs (téléphones portables pas chers et votre grille-pain), il n'y a pas de virgule flottante, de sorte que les opérations à virgule flottante doivent être émulé dans le logiciel. C'est lent -- deux ordres de grandeur plus lent que l'arithmétique des nombres entiers.
Comme je l'ai dit, les gens attendent de leurs téléphones portables et autres appareils à se comporter de plus en plus comme de "vrais" ordinateurs, et les concepteurs de matériel sont rapidement renforcer les Unités de police constituées pour répondre à cette demande. Sauf si vous êtes à chasser chaque dernier cycle, ou vous écrivez du code pour les très limité de Processeurs qui ont peu ou pas de virgule flottante de soutien, la performance distinction n'est pas question pour vous.
De taille différente types d'entiers:
Généralement, Processeurs sont les plus rapides à l'exploitation sur des entiers de leurs natif de la taille de mot (avec quelques mises en garde sur les systèmes 64 bits). 32 les opérations sur les bits sont souvent plus rapides que les 8 ou 16 bits opérations sur les Processeurs modernes, mais cela varie un peu entre les architectures. Aussi, n'oubliez pas que vous ne pouvez pas prendre en compte la vitesse d'un PROCESSEUR dans l'isolement; il fait partie d'un système complexe. Même si l'exploitation sur 16 bits des nombres est 2x plus lent que l'exploitation sur des nombres de 32 bits, vous pouvez monter deux fois plus de données dans la hiérarchie du cache lorsque vous représenter avec des nombres 16 bits au lieu de 32 bits. Si qui fait la différence entre le fait d'avoir toutes vos données viennent de cache au lieu de prendre fréquemment des erreurs de la mémoire cache, puis le plus rapide de l'accès à la mémoire sera l'atout le plus lent de fonctionnement de la CPU.
Autres notes:
Vectorisation pencher la balance encore plus en faveur de étroit types (
float
et 8 et 16 bits par exemple) - vous pouvez faire plusieurs opérations dans un vecteur de la même largeur. Cependant, bon vecteur de code est dur à écrire, donc c'est pas comme si vous obtenez de bénéficier de cet avantage, sans beaucoup de travail minutieux.Pourquoi il y a des différences de rendement?
Il ya vraiment seulement deux facteurs qui influent sur si oui ou non une opération est rapide sur un CPU: le circuit de la complexité de l'opération, et à la demande de l'utilisateur pour que l'opération soit rapide.
(Dans la raison) toute opération peut être réalisée rapidement, si les concepteurs de puces sont disposés à jeter suffisamment de transistors sur le problème. Mais transistors coût de l'argent (ou plutôt, en utilisant beaucoup de transistors rend votre puce plus grande, ce qui signifie que vous obtenez moins de jetons par galette et la baisse des rendements, ce qui coûte de l'argent), de sorte que les concepteurs de puces qui balance entre la façon dont beaucoup de complexité à utiliser pour les opérations, et ils le font sur la base (perçue) de la demande des utilisateurs. En gros, vous pourriez penser à la rupture des opérations en quatre catégories:
forte demande, faible complexité des opérations sera rapide sur presque n'importe quel CPU: ils sont les plus faciles, et de conférer le maximum de bénéfice de l'utilisateur par transistor.
la demande est élevée, de haute complexité des opérations sera rapide sur cher Processeurs (comme ceux utilisés dans les ordinateurs), parce que les utilisateurs sont prêts à payer pour eux. Vous n'êtes probablement pas prêt à payer un supplément de 3 $pour votre grille-pain pour avoir un rapide FP multiplier, cependant, si bon marché Cpu seront lésiner sur ces instructions.
faible de la demande, haut de la complexité des opérations sera généralement lente sur presque tous les processeurs; il n'y a simplement pas assez d'avantages pour justifier le coût.
faible demande, la faible complexité des opérations sera rapide si quelqu'un prend la peine de penser à eux, et non nulle sinon.
Pour en savoir plus:
Absolument.
Tout d'abord, bien sûr, il dépend entièrement de l'architecture du PROCESSEUR en question.
Cependant, intégrale et les types à virgule flottante sont traitées très différemment, donc la suite est presque toujours le cas:
Sur certains Processeurs, des chambres doubles peuvent être beaucoup plus lent que les flotteurs. Sur certaines architectures, il n'y a pas de matériel dédié pour les doubles, et donc ils sont manipulés par le passage de deux float-morceaux de taille à travers, vous donnant un mal de débit et de deux fois le temps de latence. Sur d'autres (le x86 FPU, par exemple), les deux types sont convertis au même format interne de 80 bits à virgule flottante, dans le cas de x86), afin que les performances sont identiques. Sur d'autres encore, les deux float et double avoir le bon matériel, mais parce que le flotteur a moins de bits, il peut être fait un peu plus rapidement, généralement en réduisant le temps de latence un peu par rapport à la double exploitation.
Avertissement: tous les horaires et les caractéristiques sont juste tiré à partir de la mémoire. Je n'ai pas l'air de tout ça, de sorte qu'il peut être mauvais. 😉
Pour les différents types d'entiers, la réponse varie énormément en fonction de l'architecture du PROCESSEUR. L'architecture x86, en raison de sa longue histoire alambiquée, a charge à la fois l'8, 16, 32 (et aujourd'hui 64) les opérations sur les bits en natif, et en général, ils sont tous aussi rapide ( ils utilisent essentiellement le même matériel, et seulement à zéro les bits de poids, si nécessaire).
Cependant, sur d'autres Processeurs, les types de données plus petit qu'un
int
peut être plus coûteuse pour load/store (l'écriture d'un octet de la mémoire peut être fait par le chargement d'un ensemble de mot de 32 bits il est situé au, et puis faire des bits de masquage pour mettre à jour l'octet dans un registre, puis d'écrire le mot en entier à l'arrière). De même, pour les types de données de plus deint
, certains Processeurs peuvent avoir à scinder l'opération en deux, le chargement, le stockage et de calcul supérieure et inférieure des moitiés séparément.Mais sur x86, la réponse est que la plupart du temps n'a pas d'importance. Pour des raisons historiques, le CPU est nécessaire d'avoir assez de soutien solide pour chaque type de données. Donc, la seule différence que vous remarquerez est que virgule flottante ops avoir plus de temps de latence (mais une production similaire, de sorte qu'ils ne sont pas plus lent en soi, au moins si vous écrivez votre code correctement)
Je ne pense pas que quelqu'un a mentionné l'entier règles de promotion. En C/C++ standard, aucune opération ne peut être effectuée que sur un type plus petit que
int
. Si char ou short arriver à être plus petits que les int sur la plate-forme actuelle, ils sont implicitement promus en int (ce qui est une source majeure de bugs). Le compilateur est nécessaire pour ce faire implicite de la promotion, il n'y a pas moyen de contourner cela sans violer la norme.L'entier des promotions signifie qu'aucune opération (addition, bit à bit, logique, etc etc) dans la langue peut se produire sur un plus petit nombre entier de type int. Ainsi, les opérations sur les char/court/int sont généralement tout aussi rapide, comme les anciennes sont promus à ce dernier.
Et sur le dessus de l'entier des promotions, il y a "l'habitude de l'arithmétique de conversions", ce qui signifie que C s'efforce de rendre les deux opérandes de même type, de la conversion de l'un d'eux à la plus grande des deux, devraient-ils être différents.
Cependant, le PROCESSEUR peut effectuer diverses load/store opérations sur 8, 16, 32 etc niveau. Sur 8 et 16 bits architectures, cela signifie souvent que 8 et 16 bits types sont plus rapides en dépit de l'entier des promotions. Sur un 32 bits CPU, il pourrait en fait signifier que les plus petits sont les types de plus lent, parce qu'il veut avoir tout parfaitement alignées en 32 bits morceaux. 32 bits compilateurs généralement optimiser la vitesse et de répartir les petits types d'entiers dans un espace plus grand que le nombre spécifié.
Même si en général le plus petit entier types de cours prennent moins d'espace que les plus grands, donc si vous avez l'intention d'optimiser pour la taille de la RAM, ils sont à préférer.
uint8_t b=255;
et puis neuint8_t a = (b + 1)/256;
alors le résultat doit être de 1 et non de 0. Si vous avezuint8_t b; b << 15
le compilateur doit invoquer un comportement indéfini dans le casint
est de 16 bits. Et ainsi de suite.La première réponse ci-dessus est grande et j'ai copié un petit bloc de travers à la suite double (car c'est là que j'ai fini premier).
Sont "char" et "la petite int" plus lent que "int"?
J'aimerais vous proposons le code suivant laquelle les profils de l'allocation, l'initialisation et de faire une opération arithmétique sur les différents entier tailles:
Mes résultats dans MSVC sur i7 4790k:
Initialiser & Set 1100100 8 bits entiers pris: 444us
Ajouter 5 à 1100100 8 bits entiers pris: 358us
Initialiser & Set 1100100 16 bits entiers pris: 666us
Ajouter 5 à 1100100 16 bits entiers pris: 359us
Initialiser & Set 1100100 32 bits entiers pris: 870us
Ajouter 5 à 1100100 32 bits entiers pris: 276us
Initialiser & Set 1100100 les entiers 64 bits pris: 2201us
Ajouter 5 à 1100100 les entiers 64 bits pris: 659us
Oui. Cependant, c'est beaucoup de plate-forme et un PROCESSEUR spécifique. Les différentes plateformes de faire des opérations arithmétiques à des vitesses différentes.
Cela étant dit, la réponse à la question est un peu plus spécifique.
pow()
est d'un usage général, une routine qui fonctionne sur des valeurs doubles. En le nourrissant des valeurs entières, il est encore en train de faire tous les travaux qui seraient nécessaires pour gérer les non-exposants entiers. L'aide directe de la multiplication ignore beaucoup de la complexité, qui est l'endroit où la vitesse est en jeu. Ce n'est vraiment pas un problème (beaucoup) de différents types, mais plutôt de passer à côté d'une grande quantité de code complexe nécessaire pour faire la fonction pow avec tout exposant.double
mathématiques sera probablement lente, car il ne peut pas être stockée dans un registre unique. Cependant, des entiers 32 bits sera probablement très vite. Le nombre et les types font une énorme différence, mais il y a beaucoup d'autres questions... à Vous de voir ce beaucoup plus dans le système intégré de travail, d'ailleurs, car cela a tendance à être TRÈS limité par rapport à l'objectif général du bureau de calcul...Dépend de la composition du processeur et de la plate-forme.
Plates-formes qui ont un flottant coprocesseur peut être plus lent que l'intégrale de l'arithmétique en raison du fait que les valeurs doivent être transférés vers et depuis le coprocesseur.
Si traitement en virgule flottante est dans le core du processeur, le temps d'exécution peut être négligeable.
Si les calculs en virgule flottante sont émulées par le logiciel, alors partie intégrante de l'arithmétique sera plus rapide.
En cas de doute, de profil.
Obtenir la programmation fonctionne correctement et robuste avant de les optimiser.
Non, pas vraiment. Cela dépend bien sûr de l'UC et du compilateur, mais la différence de performance est généralement négligeable - si il n'y a même aucun.
double
plus est, littéralement, 14 fois plus lent queint
plus, qui peut certainement être ressentie dans FP-lourds apps 😉Il y a certainement une différence entre les nombres à virgule flottante et l'arithmétique des nombres entiers. En fonction de la CPU du matériel et des micro-instructions, vous obtenez des performances différentes et/ou de précision. De bonnes conditions d'utilisation google pour les descriptions précises (je ne sais pas exactement non plus):
En ce qui concerne la taille des entiers, il est préférable d'utiliser la plate-forme/architecture de la taille de mot (ou double), ce qui revient à un
int32_t
sur x86 etint64_t
sur x86_64. Certains processeurs peuvent avoir intrinsèque des instructions qui gèrent plusieurs de ces valeurs à la fois (comme l'ESS (virgule flottante) et MMX), ce qui permettra d'accélérer parallèle des additions ou des multiplications.Généralement, math entier est plus rapide que de mathématiques à virgule flottante. C'est parce que entier mathématiques consiste à simplifier les calculs. Cependant, dans la plupart des opérations que nous parlons moins d'une douzaine d'horloges. Pas millis, les micros, les nanos, ou les tiques; horloges. Celles qui surviennent entre 2 à 3 milliards de fois par seconde moderne cœurs. Aussi, depuis le 486 beaucoup de cœurs de disposer d'un ensemble de Traitement à virgule Flottante de Parts ou d'Unités de police constituées, qui sont programmés pour effectuer l'arithmétique à virgule flottante de manière efficace, et souvent en parallèle avec le CPU.
Comme un résultat, bien que techniquement, c'est plus lent, des calculs en virgule flottante sont toujours aussi rapides que toute tentative de la différence aurait plus d'erreur inhérente au mécanisme de synchronisation et de planification de thread qu'il prend pour effectuer le calcul. Utiliser des entiers quand vous pouvez, mais de comprendre quand vous ne pouvez pas, et ne vous inquiétez pas trop à propos de relative de la vitesse de calcul.