Question But de l'alignement de la mémoire


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


139
2017-12-19 15:18


origine


Réponses:


C'est une limitation de nombreux processeurs sous-jacents. Généralement, il peut être contourné en faisant 4 seul octet inefficace plutôt que récupère mot efficace chercher, mais beaucoup d'identificateurs de langue a décidé qu'il serait plus facile de les interdire et forcer tout à aligner.

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


46
2017-12-19 15:20



Le sous-système de mémoire sur un processeur moderne est limité à l'accès à la mémoire à la granularité et à l'alignement de sa taille de mot; c'est le cas pour plusieurs raisons.

La vitesse

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

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

De ce fait, il est très facile de lire deux octets de moins que quatre. 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 très probablement aligné comme indiqué ici:

Struct Layout

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

Supposons que vous ayez une version compacte de la structure, peut-être du réseau où elle était compressée pour une efficacité de transmission; cela pourrait ressembler à ceci:

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 d'un octet à gauche pour le placer dans un registre à 16 bits; un travail supplémentaire, mais la plupart peuvent gérer cela en un seul cycle.

Lorsque vous demandez 32 bits à partir de 0x0001, vous obtenez une amplification 2X. Le processeur va lire à partir de 0x0000 dans le registre de résultats et décaler à gauche 1 octet, puis relire de 0x0004 dans un registre temporaire, décaler à droite 3 octets, puis OR avec le registre de résultat.

Gamme

Pour tout espace d'adressage donné, si l'architecture peut supposer que les 2 RLSP sont toujours 0 (par exemple, les machines 32 bits), il peut accéder à 4 fois plus de mémoire (2 sauvés bits peuvent représenter 4 états distincts), ou la même quantité de mémoire avec 2 bits pour quelque chose comme drapeaux. En prenant les 2 LSB d'une adresse, vous obtenez un alignement sur 4 octets. également appelé un foulée 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’est-à-dire que les deux derniers bits continueront toujours à ê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 de moins sur le processeur et 2 traces de moins sur la carte de circuit.

Atomicité

Le processeur peut fonctionner de manière atomique sur un mot de mémoire aligné, ce qui signifie qu'aucune autre instruction ne peut interrompre cette opération. Ceci est essentiel au bon fonctionnement de beaucoup structures de données sans verrouillage et autre concurrence les paradigmes.

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 manière similaire).

Il y a beaucoup plus d'avantages à respecter l'alignement de la mémoire que vous pouvez lire à cet article IBM.

L'utilisation principale d'un ordinateur consiste à transformer des données. Les architectures et technologies de mémoire modernes ont été optimisées au fil des décennies pour faciliter l’obtention de plus de données, d’entrée, de sortie et entre des unités d’exécution plus nombreuses et plus rapides.

Bonus: Caches

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

Pour plus d’informations sur les performances pouvant être obtenues en exploitant les caches, consultez Galerie des effets de cache de processeur; de ceci question sur les tailles des lignes de cache

La compréhension des lignes de cache peut être importante pour certains types d’optimisations de programmes. 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 mauvais alignement, l'opération sera deux fois plus lente.


233
2017-12-19 15:51



vous pouvez avec certains processeurs (le nehalem peut le faire), mais auparavant tout accès à la mémoire était aligné sur une ligne 64 bits (ou 32 bits), car le bus a une largeur de 64 bits, il fallait donc récupérer 64 bits à la fois, «morceaux» de 64 bits.

Donc, si vous vouliez obtenir un seul octet, vous avez récupéré le bloc 64 bits, puis masqué les bits que vous ne vouliez pas. Facile et rapide si votre octet était au bon endroit, mais s'il se trouvait au milieu de ce segment 64 bits, vous devriez masquer les bits indésirables et transférer les données au bon endroit. Pire encore, si vous vouliez une variable de 2 octets, mais que celle-ci était divisée en deux parties, 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 s'exécute plus rapidement et plus efficacement au prix d'un gaspillage de mémoire.


18
2017-12-19 15:31



Fondamentalement, la raison en 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 sur le cache L1 sur puce, qui est souvent de 32 Ko ces jours-ci. Mais le bus de mémoire qui connecte le cache L1 au processeur aura la largeur de la ligne de cache beaucoup plus petite. Ce sera de l'ordre de 128 morceaux.

Alors:

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

Les accès mal alignés chevaucheront parfois deux lignes de cache, ce qui nécessitera une lecture de cache entièrement nouvelle pour obtenir les données. Il pourrait même manquer tout le chemin à la DRAM.

De plus, une partie du processeur devra rester sur sa tête pour rassembler un seul objet parmi 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 niveau, 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 du processeur, mais ce matériel manque peut-être d'objets mal alignés, car il est probablement plus judicieux d'utiliser ces transistors pour accélérer correctement optimisé programmes.

Quoi qu’il en soit, la seconde lecture de mémoire parfois nécessaire ralentirait le pipeline, quel que soit le niveau de matériel dédié (hypothétiquement et bêtement) à la correction des opérations de mémoire mal alignées.


3
2018-03-01 18:38



@joshperry a donné une excellente réponse à cette question. En plus de sa réponse, j'ai des chiffres qui montrent graphiquement les effets décrits, en particulier l’amplification 2X. Voici un lien vers un Feuille de calcul Google montrant à quoi ressemble l'effet des différents alignements de mots. En outre, 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 avec un processeur Intel Core i7 64 bits à 2 cœurs à 2,8 GHz et 16 Go de RAM.

enter image description here


3
2018-04-06 14:26



Si un système avec une mémoire adressable par octet dispose d'un bus de mémoire de 32 bits, cela signifie qu'il existe des systèmes de mémoire de quatre octets, tous câblés pour lire ou écrire la même adresse. Une lecture alignée de 32 bits nécessitera des informations stockées dans la même adresse dans les quatre systèmes de mémoire, de sorte que tous les systèmes puissent fournir des données simultanément. Une lecture non alignée de 32 bits nécessiterait que certains systèmes de mémoire renvoient des données d'une adresse, et certains renvoient des données provenant de l'adresse 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 leur permet d'utiliser une adresse supérieure à celle spécifiée) et la complexité d'un système de mémoire; la plupart des systèmes de mémoire de base ne peuvent tout simplement pas renvoyer des portions de mots de 32 bits différents en même temps.


2
2018-06-15 20:21



Si vous avez un bus de données 32 bits, les lignes d'adresse du bus d'adresse connectées à la mémoire commenceront à partir de A2Ainsi, seules les adresses alignées sur 32 bits sont accessibles dans un seul cycle de bus.

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

Certains architectures / jeux d'instructions ne prennent pas en charge les accès non alignés et génèrent une exception sur 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 supplémentaires.


1
2018-06-19 20:10



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

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

Une charge de 32 bits par rapport à quatre charges de 8 bits ne fera pas beaucoup de différence sur la plupart des processeurs modernes. Que les données soient déjà en cache ou non aura un effet beaucoup plus important.


-1
2017-12-19 15:28