Question

Quelle est la différence entre un accès mémoire aligné et non aligné ?

Je travaille sur un DSP TMS320C64x, et je souhaite utiliser les fonctions intrinsèques (fonctions C pour les instructions d'assemblage) et il a

ushort & _amem2(void *ptr);
ushort & _mem2(void *ptr);

_amem2 fait un accès aligné de 2 octets et _mem2 effectue un accès non aligné.

Quand dois-je utiliser lequel ?

Était-ce utile?

La solution

Un accès à la mémoire alignée signifie que le pointeur (comme un nombre entier) est un multiple d'une valeur spécifique d'un type appelé l'alignement. L'alignement est l'adresse physique multiple où le type doit être, ou doit être stocké (par exemple pour des raisons de performance) sur une CPU. Par exemple, un processeur peut exiger que les adresses sont faites par toutes les charges à deux octets ou les magasins qui sont des multiples de deux. Pour les petits types primitifs (de moins de 4 octets), l'alignement est presque toujours la taille du type. Pour struct, l'alignement est généralement l'alignement maximal d'un membre.

Le compilateur C met toujours les variables que vous déclarez à des adresses qui satisfont l'alignement « correct ». Donc, si ptr points par exemple une variable uint16_t, il sera aligné et vous pouvez utiliser _amem2. Vous devez utiliser _mem2 uniquement si vous accédez par exemple un tableau d'octets emballé reçu par l'intermédiaire d'E / S, ou d'octets au milieu d'une chaîne.

Autres conseils

De nombreuses architectures informatiques mémoire dans « mots » de plusieurs octets chacun. Par exemple, l'architecture Intel 32 bits stocke les mots de 32 bits, chacun des 4 octets. La mémoire est traitée au niveau d'un seul octet, cependant; donc une adresse peut être « aligné », ce qui signifie qu'il commence à une limite de mot, ou « non alignés », ce qui signifie qu'il ne fonctionne pas.

Sur certaines architectures certaines opérations de mémoire peuvent être plus lente, voire totalement non autorisés sur les adresses non alignés.

Donc, si vous savez que vos adresses sont alignées sur les bonnes adresses, vous pouvez utiliser _amem2 (), pour la vitesse. Dans le cas contraire, vous devez utiliser _mem2 ().

Les adresses alignées sont celles qui sont des multiples de la taille d'accès en question.

  • Les accès de mots de 4 octets sur des adresses multiples de 4 seront alignés
  • L'accès de 4 octets à partir de l'adresse (disons) 3 sera un accès non aligné

Il est très probable que le _mem2 la fonction qui fonctionnera également pour les accès non alignés sera moins optimale pour faire fonctionner les alignements corrects dans son code.Cela signifie que le _mem2 la fonction est susceptible d'être plus coûteuse que sa _amem2 version.

Ainsi, lorsque vous avez besoin de performances (notamment lorsque vous savez que la latence d’accès est élevée), il serait prudent d’identifier quand vous pouvez utiliser l’accès aligné.Le _amem2 existe dans ce but précis : pour vous offrir des performances lorsque vous savez que l'accès est aligné.

Lorsqu'il s'agit d'accès à 2 octets, l'identification des opérations alignées est très simple.
Si toutes les adresses d'accès pour l'opération sont « paires » (c'est-à-dire que leur LSB est nul), vous disposez d'un alignement sur 2 octets.Cela peut être facilement vérifié avec,

if (address & 1) // is true
    /* we have an odd address; not aligned */
else
    /* we have an even address; its aligned to 2-bytes */

Je sais que c'est une vieille question avec une réponse choisie, mais na pas voir quelqu'un expliquer la réponse à ce qui est la différence entre l'accès mémoire et unaligned ... Alignés

Que ce soit Dram Sram ou flash ou autre. Prenez un sram comme un exemple simple, il est construit à partir de bits un Sram spécifique sera construit à partir d'un nombre fixe de bits de large et un nombre fixe de lignes profondes. permet de dire 32 bits de large et plusieurs / plusieurs lignes profondes.

si je fais une écriture 32 bits pour traiter 0x0000 dans ce SRAM, le contrôleur de mémoire autour de ce SRAM peut simplement faire un seul cycle d'écriture à la ligne 0.

si je fais une écriture 32 bits pour répondre 0x0001 dans ce sram, en supposant que est autorisé, le contrôleur devra faire une lecture de la ligne 0, modifier trois des octets, en conservant un, et d'écrire que de la ligne 0, puis lire la ligne 1 modifie un octet en laissant les trois autres comme trouvé et écrire que le dos. octets qui sont modifiés ou ne pas avoir à faire avec boutisme pour le système.

Le premier est aligné et celui-ci non alignés, clairement une différence de performance, plus besoin de la logique supplémentaire pour être en mesure de faire les quatre cycles de mémoire et de fusionner les voies d'octets.

Si je devais lire 32 bits d'adresse 0x0000 puis une lecture unique de la ligne 0, fait. Mais lire 0x0001 et je dois faire deux lectures row0 et row1 et selon la conception du système juste envoyer ces 64 bits au processeur peut-être deux horloges de bus au lieu d'un. ou le contrôleur de mémoire comporte une logique supplémentaire de telle sorte que les 32 bits sont alignés sur le bus de données en un seul cycle de bus.

16 bits lit sont un peu mieux, une lecture de 0x0000, 0x0001 et 0x0002 ne serait qu'une lecture de row0 et pourrait en fonction de la conception du système / processeur envoyer ces 32 bits en arrière et le processeur les extraits ou les déplacer dans la le contrôleur de mémoire de sorte qu'ils arrivent sur les voies d'octets spécifiques de sorte que le processeur n'a pas à tourner autour. L'un ou l'autre doit sinon les deux. Une lecture de 0x0003 bien est comme ci-dessus il faut lire la ligne 0 et row1 comme un de vos octets est dans chaque puis, soit envoyer des 64 bits de retour pour le processeur à extraire ou le contrôleur de mémoire combine les bits dans une réponse de bus de 32 bits ( en supposant que le bus entre le contrôleur de processeur et la mémoire est large de 32 bits pour ces exemples).

Une écriture de 16 bits mais finit toujours avec au moins une lecture-modification-écriture dans cet exemple SRAM, 0x0000 d'adresse, 0x0001 et 0x0002 lecture row0 modifier deux octets et d'écriture arrière. 0x0003 adresse lue deux rangées modifier un octet chacun et écrire de nouveau.

8 bits il vous suffit de lire une ligne contenant cet octet, écrit bien sont une lecture-modification-écriture d'une ligne.

Le na pas ARMv4 comme unaligned bien que vous pouvez désactiver le piège et le résultat est que vous attendez ci-dessus, pas important, les bras actuels permettent unaligned et vous donner le comportement ci-dessus, vous pouvez changer un peu dans un registre de contrôle et il provoquera l'arrêt des transferts non alignés. MIPS utilisé pour permettre non, pas sûr de ce qu'ils font maintenant. x86, 68K etc, a été autorisé et le contrôleur de mémoire peut-être dû faire le plus de travail.

Les dessins qui lui permettent DonT sont clairement les performances et moins de logique à ce que certains diraient est un fardeau pour les programmeurs d'autres pourraient dire qu'il n'y a pas de travail supplémentaire sur le programmeur ou plus facile sur le programmeur. ou non aligné, vous pouvez également voir pourquoi il peut être préférable d'essayer de ne pas enregistrer une mémoire en faisant 8 bits variables, mais aller de l'avant et graver un mot de 32 bits ou quelle que soit la taille naturelle d'un registre ou le bus est. Il peut aider votre performance à un faible coût de quelques octets. Sans parler du code supplémentaire le compilateur aurait besoin d'ajouter pour faire le laisse dire 32 bits registre mimer une variable 8 bits, le masquage et signe parfois l'extension. Où utilisant des tailles natives de registre ces instructions supplémentaires ne sont pas nécessaires. Vous pouvez également emballer plusieurs choses dans un emplacement de bus / mémoire large et faire un cycle de mémoire pour recueillir ou écrire les utiliser ensuite des instructions supplémentaires pour manipulate entre les registres ne coûte RAM et un lavage possible sur le nombre d'instructions.

Je ne suis d'accord que le compilateur alignera toujours le droit de données pour la cible, il existe des moyens de briser cela. Et si la cible ne marche pas soutenir unaligned vous frapperez la faute. Les programmeurs auraient jamais besoin de parler si le compilateur a toujours fait droit basé sur un code juridique que vous pourriez trouver, il n'y aurait aucune raison pour que cette question moins que ce soit pour la performance. si vous ne contrôler l'adresse ptr vide à aligner ou non, vous devez utiliser la mem2 () l'accès unaligned tout le temps ou vous devez faire un if-then-else dans votre code basé sur la valeur du PTR nik souligné. en déclarant comme nul le compilateur C a maintenant aucun moyen de traiter correctement votre alignement et il ne sera garanti. si vous prenez un char * PRT et le nourrir à ces fonctions tous les paris sont ouverts sur le compilateur l'obtenir droite sans vous ajouter du code supplémentaire soit enterré dans la fonction mem2 () ou en dehors de ces deux fonctions. de façon écrit dans votre mem2 () question est la seule réponse.

DRAM dire utilisé dans votre bureau / ordinateur portable a tendance à être 64 ou 72 (avec ecc) bits de large, et chaque accès à eux est aligné. Même si les bâtons de mémoire sont en fait constitués de 8 bits de large ou 16 ou 32 bits de large puces. (Ce qui peut changer avec les téléphones / comprimés pour diverses raisons), le contrôleur de mémoire et, idéalement, au moins une mémoire cache se trouve en face de ce dram de sorte que les non alignées ou même alignées les accès qui sont plus petits que la largeur de bus de lecture-modification-écriture sont traitées avec dans le cache SRAM qui est beaucoup plus rapide, et les accès de mémoire DRAM sont tous alignés largeur de bus accède. Si vous avez pas de cache devant le dram et le contrôleur est conçu pour une largeur complète accède alors qui est la plus mauvaise performance, si elle est conçue pour éclairer les voies d'octets séparément (en supposant large puces 8 bits) alors vous n'avez pas la lecture modifier -writes mais un contrôleur plus compliqué. si le cas d'utilisation typique est avec un cache (s'il y en a un dans la conception), il ne peut pas logique d'avoir ce travail supplémentaire dans le contrôleur pour chaque voie d'octets, mais avoir juste savoir comment faire toute la largeur de bus transferts de taille ou des multiples de.

_mem2 est plus générale. Il va fonctionner si ptr est aligné ou non. _amem2 est plus stricte: il faut que ptr soit aligné (mais est sans doute un peu plus efficace). Il faut donc utiliser _mem2 à moins que vous pouvez garantir que ptr est toujours aligné.

De nombreux processeurs ont des restrictions d'alignement sur l'accès mémoire. accès Unaligned soit génère une interruption d'exception (par exemple, ARM), ou est simplement plus lente (par exemple x86).

_mem2 est probablement mis en oeuvre comme l'extraction et à l'aide de deux octets ou décalage et des opérations de manipulation de bits pour faire un ushort 16 bits sur eux.

_amem2 probablement juste le lit ushort 16 bits du PTR spécifié.

Je ne sais pas TMS320C64x spécifiquement, mais je suppose que nécessite un alignement de 16 bits pour la mémoire 16 bits accès. Vous pouvez donc utiliser toujours mais avec <=> pénalité de performance, et quand vous pouvez <=> garantir que ptr est une adresse même.

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