web-dev-qa-db-fra.com

But de l'alignement de la mémoire

Certes, je ne comprends pas. Supposons que vous ayez une mémoire avec un mot mémoire de 1 octet. Pourquoi ne pouvez-vous pas accéder à une variable longue de 4 octets dans un accès mémoire unique sur une adresse non alignée (c'est-à-dire, non divisible par 4), comme c'est le cas avec les adresses alignées?

171
ark

C'est une limitation de nombreux processeurs sous-jacents. On peut généralement contourner ce problème en effectuant 4 extractions d'octets uniques inefficaces plutôt qu'en une extraction efficace de Word, mais de nombreux spécificateurs de langue ont décidé qu'il serait plus simple de les interdire et de tout forcer à être alignés.

Il y a beaucoup plus d'informations dans ce lien que l'OP a découvert.

56
Paul Tomblin

Le sous-système de mémoire d’un processeur moderne est limité à l’accès à la mémoire avec la granularité et l’alignement de la taille de Word; c'est le cas pour un certain nombre de raisons.

La vitesse

Les processeurs modernes disposent de plusieurs niveaux de mémoire cache dans lesquels les données doivent être extraites; la prise en charge des lectures sur un octet rendrait le débit du sous-système mémoire étroitement lié au débit de l'unité d'exécution (c-à-d. lié à l'unité centrale); tout cela rappelle comment le mode PIO a été dépassé par le DMA pour plusieurs des mêmes raisons sur les disques durs.

La CPU lit toujours à sa taille de Word (4 octets sur un processeur 32 bits), donc lorsque vous effectuez un accès à une adresse non alignée - sur un processeur qui: prend en charge - le processeur va lire plusieurs mots. La CPU lira chaque mot de la mémoire que l'adresse demandée chevauche. Cela entraîne une amplification allant jusqu'à 2 fois le nombre de transactions en mémoire nécessaires pour accéder aux données demandées.

De ce fait, la lecture de deux octets sur quatre peut être très lente. Par exemple, disons que vous avez une structure en mémoire qui ressemble à ceci:

struct mystruct {
    char c;  // one byte
    int i;   // four bytes
    short s; // two bytes
}

Sur un processeur 32 bits, il serait probablement aligné comme ci-dessous:

Struct Layout

Le processeur peut lire chacun de ces membres en une seule transaction.

Supposons que vous disposiez d'une version compacte de la structure, provenant peut-être du réseau où elle était compressée pour l'efficacité de la transmission. cela pourrait ressembler à quelque chose comme ça:

Packed Struct

La lecture du premier octet sera la même.

Lorsque vous demandez au processeur de vous donner 16 bits à partir de 0x0005, il devra lire un mot à partir de 0x0004 et décaler de 1 octet à gauche pour le placer dans un registre à 16 bits; un peu de travail supplémentaire, mais la plupart peuvent gérer cela en un cycle.

Lorsque vous demandez 32 bits à 0x0001, vous obtenez une amplification 2X. Le processeur lira de 0x0000 dans le registre de résultats et décalera d'un octet à gauche, puis relira de 0x0004 dans un registre temporaire, décalera de 3 octets à droite, puis OR avec le registre de résultats.

Gamme

Pour tout espace d'adressage donné, si l'architecture peut supposer que les 2 LSB sont toujours égaux à 0 (par exemple, les machines 32 bits), elle peut accéder à 4 fois plus de mémoire (les 2 bits sauvegardés peuvent représenter 4 états distincts), ou le même montant. de mémoire avec 2 bits pour quelque chose comme des drapeaux. Supprimer les deux LSB d'une adresse vous donnerait un alignement de 4 octets; également appelé stride de 4 octets. Chaque fois qu'une adresse est incrémentée, elle incrémente effectivement le bit 2 et non le bit 0, c.-à-d. Que les 2 derniers bits continueront toujours d'être 00.

Cela peut même affecter la conception physique du système. Si le bus d'adresse nécessite 2 bits de moins, il peut y avoir 2 broches en moins sur la CPU et 2 traces en moins sur la carte de circuit imprimé.

Atomicité

La CPU peut opérer de manière atomique sur un mot aligné de la mémoire, ce qui signifie qu'aucune autre instruction ne peut interrompre cette opération. Ceci est essentiel au bon fonctionnement de nombreux structures de données sans verrouillage et autres simultanéité .

Conclusion

Le système de mémoire d’un processeur est un peu plus complexe et complexe que celui décrit ici; Une discussion sur comment un processeur x86 traite réellement la mémoire peut aider (de nombreux processeurs fonctionnent de la même manière).

L'adhésion à l'alignement de la mémoire présente de nombreux autres avantages que vous pouvez lire à l'adresse cet article IBM .

La principale utilisation d'un ordinateur est de transformer des données. Les architectures et les technologies de mémoire modernes ont été optimisées au fil des décennies pour faciliter l’obtention de davantage de données, en entrée et en sortie, et entre des unités d’exécution plus nombreuses et plus rapides, de manière extrêmement fiable.

Bonus: Caches

Un autre alignement sur les performances auquel j'ai fait allusion précédemment est l'alignement sur les lignes de cache qui sont (par exemple, sur certains processeurs) 64B.

Pour plus d'informations sur les performances pouvant être obtenues en exploitant les caches, consultez Galerie des effets de cache de processeur ; à partir de ceci question sur la taille des lignes de cache

La compréhension des lignes de cache peut être importante pour certains types d’optimisation de programme. Par exemple, l'alignement des données peut déterminer si une opération touche une ou deux lignes de cache. Comme nous l'avons vu dans l'exemple ci-dessus, cela peut facilement signifier que, dans le cas d'un désalignement, l'opération sera deux fois plus lente.

281
joshperry

vous pouvez avec certains processeurs ( le nehalem peut le faire ), mais auparavant tous les accès mémoire étaient alignés sur une ligne 64 bits (ou 32 bits), car le bus a une largeur de 64 bits, vous aviez chercher 64 bits à la fois, et il était beaucoup plus facile de les récupérer en "morceaux" alignés de 64 bits.

Donc, si vous vouliez obtenir un seul octet, vous récupériez le bloc de 64 bits, puis masquiez les bits que vous ne vouliez pas. Facile et rapide si votre octet se trouvait à l'extrémité droite, mais s'il se trouvait au milieu de ce bloc de 64 bits, vous devrez masquer les bits non désirés, puis déplacer les données au bon endroit. Pire, si vous vouliez une variable de 2 octets, mais que celle-ci soit divisée en 2 morceaux, cela nécessitait le double des accès mémoire requis.

Ainsi, comme tout le monde pense que la mémoire est bon marché, ils ont simplement obligé le compilateur à aligner les données sur la taille des blocs du processeur afin que votre code soit exécuté plus rapidement et plus efficacement, au détriment de la perte de mémoire.

22
gbjbaanb

La raison principale est que le bus de mémoire a une longueur spécifique beaucoup plus petite que la taille de la mémoire.

Ainsi, le processeur lit le cache L1 sur puce, qui fait souvent 32 Ko actuellement. Mais le bus de mémoire qui connecte le cache L1 à la CPU aura la largeur beaucoup plus petite de la taille de la ligne de cache. Ce sera de l'ordre de 128 bits.

Alors:

262,144 bits - size of memory
    128 bits - size of bus

Les accès mal alignés chevauchent parfois deux lignes de cache, ce qui nécessite une lecture du cache entièrement nouvelle pour obtenir les données. Il se peut même qu'il manque la totalité de la DRAM.

En outre, une partie de la CPU devra rester sur la tête pour rassembler un seul objet à partir de ces deux lignes de cache différentes, chacune contenant une partie des données. Sur une ligne, ce sera dans les bits de très haut ordre, dans l'autre, les bits de très faible poids.

Il y aura du matériel dédié entièrement intégré dans le pipeline qui gère le déplacement des objets alignés sur les bits nécessaires du bus de données de la CPU, mais ce matériel peut manquer pour les objets mal alignés, car il est probablement plus judicieux d'utiliser ces transistors pour accélérer correctement optimisés programmes.

Dans tous les cas, la deuxième lecture mémoire parfois nécessaire ralentirait le pipeline, quel que soit le matériel utilisé à des fins spécifiques (hypothétiquement et bêtement) dédiée à la correction des opérations de mémoire mal alignées.

4
DigitalRoss

@joshperry a donné une excellente réponse à cette question. En plus de sa réponse, j'ai quelques chiffres qui montrent graphiquement les effets qui ont été décrits, en particulier l'amplification 2X. Voici un lien vers un tableur Google montrant l'effet de différents alignements Word. De plus, voici un lien vers un Github Gist avec le code pour le test. Le code de test est adapté de l'article écrit par Jonathan Rentzsch auquel @joshperry a fait référence. Les tests ont été exécutés sur un Macbook Pro doté d’un processeur Intel Core i7 64 bits quad-core à 2,8 GHz et de 16 Go de RAM.

enter image description here

3
adino

Si un système avec une mémoire adressable sur des octets a un bus de mémoire d'une largeur de 32 bits, cela signifie qu'il existe effectivement des systèmes de mémoire d'une largeur de quatre octets, tous câblés pour lire ou écrire la même adresse. Une lecture alignée sur 32 bits nécessitera des informations stockées à la même adresse dans les quatre systèmes de mémoire, afin que tous les systèmes puissent fournir des données simultanément. Une lecture 32 bits non alignée nécessiterait que certains systèmes de mémoire renvoient des données d'une adresse et d'autres pour renvoyer des données de l'adresse la plus élevée suivante. Bien que certains systèmes de mémoire soient optimisés pour pouvoir répondre à de telles demandes (en plus de leur adresse, ils ont effectivement un signal "plus un" qui les pousse à utiliser une adresse supérieure à celle spécifiée), mais une telle fonctionnalité entraîne des coûts considérables. et complexité d'un système de mémoire; la plupart des systèmes de mémoire courants ne peuvent tout simplement pas renvoyer des portions de différents mots de 32 bits en même temps.

2
supercat

Si vous avez un bus de données 32 bits, les lignes d’adresse du bus d’adresse connectées à la mémoire démarrent à partir de A2, de sorte que seules les adresses alignées sur 32 bits peuvent être accédées dans un seul cycle de bus.

Donc, si un mot couvre une limite d’alignement d’adresse - c’est-à-dire un pour données 16/32 bits ou A1 pour 32 bits, les données ne sont pas nulles, il faut deux cycles de bus pour obtenir les données.

Certaines architectures/jeux d'instructions ne supportent pas les accès non alignés et généreront une exception lors de telles tentatives. Par conséquent, le code d'accès non aligné généré par le compilateur nécessite non seulement des cycles de bus supplémentaires, mais également des instructions, ce qui le rend encore moins efficace.

1
Clifford

Sur PowerPC, vous pouvez charger un entier à partir d’une adresse impaire sans aucun problème.

Sparc et I86 et (je pense) Itatnium soulèvent des exceptions matérielles lorsque vous essayez ceci.

Une charge de 32 bits contre quatre charges de 8 bits ne fera pas beaucoup de différence sur les processeurs les plus modernes. Que les données soient déjà dans le cache ou non aura un effet beaucoup plus important.

0
James Anderson