web-dev-qa-db-fra.com

C ++ int vs long long dans une machine 64 bits

Mon ordinateur possède un processeur 64 bits et lorsque je recherche sizeof(int), sizeof(long) et sizeof(long long), il s'avère que int et - long sont 32 bits, et long long est 64 bits. J'ai recherché la raison, et il semble que l'hypothèse populaire disant que int en C++ correspond à la taille de Word de la machine est incorrecte. Si j'ai bien compris, c'est au compilateur de définir quelle sera la taille, et le mien est Mingw-w64. La raison de ma recherche était de comprendre que si l'utilisation de types plus petits que la taille de Word est bénéfique pour la vitesse (par exemple, court = vs int) ou si cela a un effet négatif. Dans un système 32 bits, une opinion populaire est: en raison du fait que la taille du mot est int, short sera converti en int et il serait provoquer des décalages de bits supplémentaires, etc., conduisant ainsi à de moins bonnes performances. L'opinion contraire est qu'il y aura des avantages au niveau du cache (je n'y suis pas allé profondément), et l'utilisation de short serait utile pour l'économie de mémoire virtuelle. Donc, en plus de la confusion entre ce dilemme, je suis également confronté à un autre problème. Mon système est en 64 bits, et peu importe si j'utilise int ou short, il sera toujours inférieur à la taille de Word, et je commence à penser que cela ne t il est efficace d'utiliser 64 bits long long car c'est au niveau auquel le système est conçu. J'ai également lu qu'il existe une autre contrainte, qui est la bibliothèque (ILP64, LP64) du système d'exploitation qui définit les tailles de type. Dans ILP64 par défaut int est 64 bits contrairement à LP64, cela accélérerait-il le programme si j'utilisais un système d'exploitation avec prise en charge ILP64? Une fois que j'ai commencé à demander quel type dois-je utiliser pour accélérer mon programme C++, j'ai été confronté à des sujets plus profonds dans lesquels je n'ai aucune expertise et certaines explications semblent se contredire. Pouvez-vous expliquer:

1) S'il est recommandé d'utiliser long long en x64 pour obtenir des performances maximales, même pour des données de 1 à 4 octets?

2) Compromis en utilisant un type inférieur à la taille de Word (gain de mémoire vs opérations supplémentaires)

3) Est-ce qu'un ordinateur x64 où la taille de Word et int est de 64 bits, a la possibilité de traiter un court, en utilisant une taille de mot de 16 bits en utilisant ce que l'on appelle la rétrocompatibilité? Ou il doit mettre le fichier 16 bits en fichier 64 bits, et le fait que cela puisse être fait définit le système comme rétrocompatible.

4) Pouvons-nous forcer le compilateur à faire le int 64 bits?

5) Comment intégrer ILP64 dans un PC utilisant LP64?

6) Quels sont les problèmes possibles d'utilisation de code adapté aux problèmes ci-dessus avec d'autres compilateurs, systèmes d'exploitation et architectures (processeur 32 bits)?

17
UserRR

1) S'il est recommandé d'utiliser long long en x64 pour obtenir des performances maximales, même pour des données de 1 à 4 octets?

Non, et cela aggravera probablement vos performances. Par exemple, si vous utilisez des entiers 64 bits où vous auriez pu vous en sortir avec des entiers 32 bits, vous venez de doubler la quantité de données qui doivent être envoyées entre le processeur et la mémoire et la mémoire est de l'ordre de grandeur plus lente. Tous vos caches et bus de mémoire seront deux fois plus rapides.

2) Compromis en utilisant un type inférieur à la taille de Word (gain de mémoire vs opérations supplémentaires)

En règle générale, le moteur dominant des performances d'une machine moderne sera la quantité de données à stocker pour exécuter un programme. Vous verrez des falaises de performances importantes une fois que la taille de l'ensemble de travail de votre programme dépassera la capacité de vos registres, cache L1, cache L2, cache L3 et RAM, dans cet ordre.

De plus, l'utilisation d'un type de données plus petit peut être un gain si votre compilateur est suffisamment intelligent pour comprendre comment utiliser les instructions vectorielles de votre processeur (aka SSE). Les unités de traitement vectoriel modernes sont assez intelligentes pour entasser huit entiers courts de 16 bits dans le même espace que deux entiers longs de 64 bits, afin que vous puissiez effectuer quatre fois plus d'opérations à la fois.

3) Est-ce qu'un ordinateur x64 où la taille de Word et int est de 64 bits, a la possibilité de traiter un court, en utilisant une taille de mot de 16 bits en utilisant ce que l'on appelle la rétrocompatibilité? Ou il doit mettre le fichier 16 bits en fichier 64 bits, et le fait que cela puisse être fait définit le système comme rétrocompatible.

Je ne suis pas sûr de ce que vous demandez ici. En général, les machines 64 bits sont capables d'exécuter des fichiers exécutables 32 bits et 16 bits car ces fichiers exécutables antérieurs utilisent un sous-ensemble du potentiel de la machine 64 bits.

Les ensembles d'instructions matérielles sont généralement rétrocompatibles, ce qui signifie que les concepteurs de processeurs ont tendance à ajouter des capacités, mais rarement, voire jamais, à supprimer des capacités.

4) Pouvons-nous forcer le compilateur à faire l'int 64 bits?

Il existe des extensions assez standard pour tous les compilateurs qui vous permettent de travailler avec des données à taille fixe. Par exemple, le fichier d'en-tête stdint.h déclare des types tels que int64_t, uint64_t, etc.

5) Comment intégrer ILP64 dans un PC utilisant LP64?

https://software.intel.com/en-us/node/528682

6) Quels sont les problèmes possibles d'utilisation de code adapté aux problèmes ci-dessus avec d'autres compilateurs, systèmes d'exploitation et architectures (processeur 32 bits)?

Généralement, les compilateurs et les systèmes sont suffisamment intelligents pour comprendre comment exécuter votre code sur un système donné. Cependant, les processeurs 32 bits vont devoir faire un travail supplémentaire pour fonctionner sur des données 64 bits. En d'autres termes, l'exactitude ne devrait pas être un problème, mais les performances le seront.

Mais il est généralement vrai que si les performances sont vraiment essentielles pour vous, vous devez de toute façon programmer pour une architecture et une plate-forme spécifiques.

Demande de clarification: merci beaucoup! Je voulais clarifier la question no: 1. Vous dites que c'est mauvais pour la mémoire. Prenons un exemple de 32 bits int. Lorsque vous l'envoyez en mémoire, car il s'agit d'un système 64 bits, pour un entier souhaité 0xee ee ee ee, lorsque nous l'envoyons, ne deviendra-t-il pas 0x ee ee ee ee ee + 32 autres bits? Comment un processeur peut-il envoyer 32 bits lorsque la taille du mot est de 64 bits? 32 bits sont les valeurs souhaitées, mais ne seront-ils pas combinés avec 32 bits inutilisés et envoyés de cette façon? Si mon hypothèse est vraie, alors il n'y a pas de différence pour la mémoire.

Il y a deux choses à discuter ici.

Premièrement, la situation dont vous discutez ne se produit pas. Un processeur n'a pas besoin de "promouvoir" une valeur 32 bits en une valeur 64 bits afin de l'utiliser de manière appropriée. En effet, les processeurs modernes ont des modes d'accès différents qui sont capables de traiter correctement des données de tailles différentes.

Par exemple, un processeur Intel 64 bits possède un registre 64 bits nommé RAX. Cependant, ce même registre peut être utilisé en mode 32 bits en se référant à lui comme EAX, et même en modes 16 bits et 8 bits. J'ai volé un diagramme d'ici:

x86_64 enregistre rax/eax/ax/al en remplaçant le contenu complet du registre

1122334455667788
================ rax (64 bits)
        ======== eax (32 bits)
            ====  ax (16 bits)
            ==    ah (8 bits)
              ==  al (8 bits)

Entre le compilateur et l'assembleur, le code correct est généré afin qu'une valeur 32 bits soit gérée de manière appropriée.

Deuxièmement, lorsque nous parlons de surcharge de mémoire et de performances, nous devrions être plus précis. Les systèmes de mémoire modernes sont composés d'un disque, puis de la mémoire principale (RAM) et généralement de deux ou trois caches (par exemple L3, L2 et L1). La plus petite quantité de données pouvant être adressée sur le disque est appelée page , et les tailles de page sont généralement de 4096 octets (bien qu'elles ne être). Ensuite, la plus petite quantité de données pouvant être adressée en mémoire est appelée ligne de cache, qui est généralement beaucoup plus grande que 32 ou 64 bits. Sur mon ordinateur, la taille de la ligne de cache est de 64 octets. Le processeur est le seul endroit où les données sont réellement transférées et adressées au niveau Word et en dessous.

Donc, si vous souhaitez modifier un mot 64 bits dans un fichier qui réside sur le disque, alors, sur mon ordinateur, cela nécessite en fait que vous chargiez 4096 octets du disque en mémoire, puis 64 octets de la mémoire dans le L3, L2 et les caches L1, puis le processeur prend un seul mot 64 bits dans le cache L1.

Le résultat est que la taille de Word ne signifie rien pour la bande passante mémoire. Cependant, vous pouvez placer 16 de ces entiers 32 bits dans le même espace que vous pouvez en empaqueter 8 de ces entiers 64 bits. Ou vous pouvez même adapter 32 valeurs 16 bits ou 64 valeurs 8 bits dans le même espace. Si votre programme utilise de nombreuses valeurs de données différentes, vous pouvez améliorer considérablement les performances en utilisant le plus petit type de données nécessaire.

33
David