Question

Il est vrai que 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 accéder à un 4 octet variable à long dans un accès de mémoire unique sur une adresse non alignée (i.e.. Non divisible par 4), comme il est le cas avec des adresses alignées?

Était-ce utile?

La solution

Il est une limitation de nombreux processeurs sous-jacents. Généralement, il peut être contourné en faisant 4 seul octet inefficace va chercher au lieu d'un mot efficace Fetch, 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 découvert.

Autres conseils

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

Vitesse

Les processeurs modernes ont plusieurs niveaux de mémoire cache que les données doivent être tirés à travers; lit supportant un seul 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é cpu-); tout cela est sans rappeler comment mode PIO a été dépassé par DMA pour un grand nombre des mêmes raisons dans les disques durs.

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

En raison de cela, il peut très facilement être plus lent à lire deux octets de quatre. Par exemple, disons que vous avez une struct 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 montré ici:

struct Mise en page

Le processeur peut lire chacun de ces éléments en une seule transaction.

Supposons que vous aviez une version compactée du struct, peut-être du réseau où il a été emballé pour l'efficacité de la transmission; il pourrait ressembler à ceci:

Emballé Struct

La lecture du premier octet va être le même.

Quand on demande au processeur de vous informer 16 bits de 0x0005 il devra lire un mot à partir de 0x0004 et décaler à gauche de 1 octet pour le placer dans un registre de 16 bits; un travail supplémentaire, mais la plupart peut gérer que dans un cycle.

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

Plage

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 (les 2 enregistrées bits peuvent représenter 4 états distincts), ou la même quantité de mémoire avec 2 bits pour quelque chose comme des drapeaux. Prendre 2 RLSP au large d'une adresse vous donnerait un alignement de 4 octets; également appelé foulée de 4 octets. Chaque fois qu'une adresse est incrémentée il est effectivement incrémenter bit 2, pas le bit 0, à savoir, les 2 derniers bits toujours continuer à être 00.

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

atomicité

Le processeur peut fonctionner sur un mot de la mémoire alignée de façon atomique, ce qui signifie qu'aucune autre instruction peut interrompre cette opération. Cela est essentiel pour le bon fonctionnement de nombreux verrouiller libre de structures de données et d'autres paradigmes concurrence de rel="noreferrer"> .

Conclusion

Le système de mémoire d'un processeur est un peu plus complexe que ne décrit ici; une discussion sur comment un processeur x86 traite effectivement la mémoire peut aider (de nombreux processeurs fonctionnent de la même ).

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

est de transformer les données principale utilisation d'un ordinateur. les architectures de mémoire et les technologies modernes ont été optimisées au fil des décennies pour faciliter l'obtention de plus de données, dedans, dehors, et entre de plus en unités-à une exécution plus rapide d'une manière très fiable.

Bonus: Caches

Un autre alignement en fonction des résultats que je l'ai mentionné précédemment est l'alignement sur les lignes d'antémémoire qui sont (par exemple, sur certains CPU) 64B.

Pour plus d'informations sur la quantité de performances peut gagner en tirant parti de caches, jetez un oeil à Galerie du processeur d'effets Cache ; de cette sur la taille cache en ligne

  

La compréhension des lignes de cache peut être important pour certains types d'optimisations du programme. Par exemple, l'alignement des données peut déterminer si une opération touche une ou deux lignes de mémoire cache. Comme nous l'avons vu dans l'exemple ci-dessus, cela peut facilement dire que dans le cas désaligné, l'opération sera deux fois plus lent.

vous pouvez avec certains processeurs ( le nehalem pouvez faire cette ), mais auparavant tous les accès mémoire a été alignée sur une ligne de 64 bits (ou 32 bits), car le bus est large de 64 bits, il fallait chercher 64 bits à la fois, et il était beaucoup plus facile de la récupération de celles-ci en alignement « morceaux » de 64 bits.

Alors, si vous voulez obtenir un seul octet, vous alla chercher le morceau 64 bits, puis masquées les bits vous ne voulez. Facile et rapide si votre octet était à l'extrémité droite, mais si elle était au milieu de ce morceau 64 bits, vous auriez pour masquer les bits indésirables, puis déplacer les données vers le bon endroit. Pire encore, si vous voulez un 2 variable d'octets, mais qui a été divisé entre 2 morceaux, puis que nécessaire le double de la mémoire requise accède.

Alors, comme tout le monde pense que la mémoire ne coûte pas cher, ils ont juste fait le compilateur d'aligner les données sur le morceau de processeur tailles de sorte que votre code fonctionne plus rapidement et plus efficacement au coût de la mémoire perdue.

Fondamentalement, la raison est parce que le bus mémoire a une certaine longueur spécifique qui est beaucoup, beaucoup plus petite que la taille de la mémoire.

Ainsi, la CPU lit du cache sur puce L1, qui est souvent 32kb ces jours-ci. Mais le bus mémoire qui relie le cache L1 à la CPU aura la largeur considérablement plus petite de la taille de la ligne de cache. Ce sera de l'ordre de 128 bits .

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

accès mal alignées de temps en temps se chevauchent deux lignes de cache, et cela nécessitera un cache entièrement nouvelle lecture afin d'obtenir les données. Il pourrait même manquer tout le chemin de la DRAM.

En outre, une partie de la CPU devra se tenir debout sur sa tête pour mettre en place un seul objet de ces deux différentes lignes de cache qui ont chacun un morceau de données. Sur une ligne, il sera dans les bits d'ordre très élevé, dans l'autre, les bits de poids très bas.

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 peut faire défaut pour les objets mal alignés, car il est probablement plus logique d'utiliser ces transistors pour excès de vitesse des programmes optimisés correctement.

Dans tous les cas, la deuxième lecture en mémoire qui est parfois nécessaire ralentirait le pipeline, peu importe la façon dont le matériel bien à usage spécial était (hypothétiquement et bêtement) dédié à rafistoler opérations de mémoire désalignement.

@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 feuille de calcul Google montrant ce que l'effet de différents alignements de mots ressemblent. De plus, voici un lien vers un Github essentiel avec le code pour le test. Le code de test est adapté de l'article écrit par Jonathan Rentzsch qui @joshperry référencé. Les tests ont été effectués sur un Macbook Pro avec un quad-core 2,8 GHz Intel Core i7 processeur 64 bits et 16 Go de RAM.

Si un système de mémoire octet adressable dispose d'un bus mémoire à l'échelle 32 bits, cela signifie qu'il ya effectivement quatre systèmes de mémoire octets à l'échelle qui sont tous câblés pour lire ou écrire la même adresse. Un alignement de lecture de 32 bits, il faudra des informations stockées dans la même adresse dans les quatre systèmes de mémoire, de sorte que tous les systèmes peuvent fournir des données simultanément. Une lecture unaligned 32 bits nécessite des systèmes de mémoire pour renvoyer des données d'une adresse, et certains pour renvoyer des données à partir de l'adresse suivante supérieure. Bien qu'il existe des systèmes de mémoire qui sont optimisés pour être en mesure de satisfaire ces demandes (en plus de leur adresse, ils ont effectivement un signal « plus un » qui les amène à utiliser une adresse une supérieure à celle spécifiée) une telle fonctionnalité ajoute un coût considérable et de la complexité à un système de mémoire; la plupart des systèmes de mémoire des produits de base peuvent tout simplement pas retourner des portions de différents mots de 32 bits en même temps.

Si vous avez un bus de données 32 bits, les lignes d'adresse de bus d'adresse connecté à la mémoire commenceront à partir de A 2 , sont accessibles en un seul cycle de bus de sorte que seules les adresses alignées 32bit.

Donc, si un mot enjambe une frontière d'alignement d'adresse - à savoir A 0 de 16/32 données de bit ou A 1 de 32 données binaires ne sont pas nuls, deux cycles de bus sont nécessaires pour obtenir les données.

Certaines architectures / jeux d'instructions ne prennent pas en charge l'accès unaligned et généreront une exception sur ces tentatives, de sorte que le compilateur de code d'accès généré unaligned exige non seulement des cycles de bus supplémentaires, mais des instructions supplémentaires, ce qui rend encore moins efficace.

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

Sparc et I86 et (je pense) Itatnium lever des exceptions matérielles lorsque vous essayez cela.

Un 32 bits charge contre quatre 8 charges de bits isnt va faire une grande différence sur la plupart des processeurs modernes. Que les données sont déjà dans le cache ou non aura un effet beaucoup plus.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top