12
votes

Alignement de la mémoire sur les processeurs modernes?

Je vois souvent du code tel que ce qui suit lorsque, par exemple, représentant un grand bitmap en mémoire: xxx

(c'est-à-dire un bitmap attribué sous forme de bloc de mémoire contiguë avec un byTewidth aligné sur un certain nombre d'octets, le plus souvent 4.)

Un point de l'image est ensuite donné via: xxx

Cela me conduit à deux questions:

  1. alignant un tampon comme celui-ci a-t-il un impact sur les performances sur les processeurs modernes? Devrais-je m'inquiéter de l'alignement du tout, ou le compilateur le gérera-t-il?
  2. Si cela a un impact, quelqu'un pourrait-il me diriger vers une ressource pour trouver l'alignement des octets idéal pour divers processeurs?

    merci.


0 commentaires

4 Réponses :


1
votes
  • alignant un tampon comme celui-ci a un impact sur la performance sur les processeurs modernes?

    oui. Par exemple, si MEMCY est optimisé à l'aide des instructions SIMD (comme MMX / SSE), certaines opérations seront plus rapides avec la mémoire alignée. Dans certaines architectures, il existe des instructions (processeur) qui échouent si les données ne sont pas alignées, ce que quelque chose pourrait fonctionner sur votre machine mais pas dans un autre.

    avec des données alignées, vous utilisez également une meilleure utilisation des caches CPU.

    • Devrais-je m'inquiéter de l'alignement du tout ou le compilateur gérera-le?

      Je devrais vous inquiéter de l'alignement lorsque j'utilise la mémoire dynamique et que le compilateur ne peut pas gérer cela (voir la réponse à ce commentaire).

      Pour d'autres choses dans votre code, vous avez le drapeau -Malign et l'attribut aligné à jouer avec.


2 commentaires

-Malign concerne l'alignement de la pile et du code, il n'est pas pertinent ici. La mémoire est allouée avec un seul malloc qui produit un morceau contigu. Si la longueur de la ligne largeur * bytesperpixel n'est pas divisible par 4 (ou la taille du mot natif, ou un registre SIMD, ou une ligne de cache, en fonction de l'application), l'accès à de nombreuses lignes sera inalignée. . L'alignement ci-dessus rend effectivement chaque rangée légèrement plus longue que nécessaire, de sorte qu'ils sont tous alignés. Le compilateur ne peut pas faire cette optimisation. Mais dans cet exemple, l'alignement supplémentaire est un non-op car 1280 * 3% 256 = 0 .


Je sais à propos de -Malign. Je parlais de l'alignement en général.



4
votes

Oui, l'alignement a un impact sur la performance sur le moderne-- Disons X86 - Processeurs. En règle générale, les charges et les magasins de données se produisent sur les limites d'alignement naturel; Si vous obtenez une valeur de 32 bits dans un registre, cela va être le plus rapide s'il est aligné sur une frontière 32 bits déjà. Si ce n'est pas le cas, le X86 «s'en occupera-t-il pour vous», dans le sens où la CPU fera toujours la charge, mais il faudra un nombre de cycles beaucoup plus important pour le faire, car il y aura des wrangling internes à » réaligner "l'accès.

Bien sûr, dans la plupart des cas, cette surcharge est triviale. Les structures de données binaires sont fréquemment emballées de manière non alignée pour les moyens de transport sur le réseau ou pour la persistance sur le disque, et les avantages de la taille du stockage emballé l'emportent sur toute perte de fonctionnement occasionnellement sur ces données.

Mais en particulier avec de grands tampons de données uniformes qui se sont accessibles au hasard et où les performances de l'agrégat sont vraiment importantes, comme dans votre tampon de pixel ci-dessus, il est possible de conserver des structures de données alignées peuvent toujours être bénéfiques.

Notez que dans le cas de l'exemple que vous donnez ci-dessus, seule chaque "ligne" de données de pixels est alignée. Les pixels eux-mêmes sont toujours 3 octets longs et souvent non alignés dans les "lignes", il n'y a donc pas beaucoup d'avantage ici. Il existe des formats de texture, par exemple, qui ont 3 octets de données réelles par pixel et gaspillent littéralement un octet supplémentaire sur chacun pour conserver les données alignées.

Il y a d'autres informations générales ici: http://fr.wikipedia.org/wiki/data_structure_alignment < / a>

(les caractéristiques spécifiques varient entre les architectures, à la fois dans les alignements naturels, que la CPU gère automatiquement des charges / magasins non alignés, et dans la façon dont ces derniers sont chers. Dans les cas où la CPU ne gère pas l'accès magiquement, Souvent, le temps d'exécution du compilateur / C fera savoir ce qu'il peut faire ce travail pour vous.)


0 commentaires

7
votes

Cela dépend de nombreux facteurs. Si vous n'associez que les données de pixels, un octet à la fois, l'alignement ne fera aucune différence la grande majorité du temps. Pour lire / écrire un octet de données, la plupart des processeurs ne se soucient pas du tout si cet octet est sur une limite de 4 octets ou non.

Toutefois, si vous accédez à des données dans des unités supérieures à un octet (par exemple, dans des unités de 2 octets ou de 4 octets), vous verrez certainement des effets d'alignement. Pour certains processeurs (par exemple, de nombreux processeurs de RISC), il est clairement illégal d'accéder aux données non alignées à certains niveaux: tenter de lire un mot de 4 octets d'une adresse non alignée sur 4 octets générera une exception d'accès aux données (ou une exception de stockage de données ) sur un PowerPC, par exemple.

sur d'autres processeurs (par exemple x86), l'accès à des adresses non alignées est autorisé, mais il est souvent livré avec une pénalité de performance cachée. Les charges / magasins de mémoire sont souvent implémentées dans le microcode et le microcode détectera l'accès non aligné. Normalement, le microcode va chercher la quantité de 4 octets appropriée de la mémoire, mais si elle n'est pas alignée, il devra récupérer deux emplacements de 4 octets de la mémoire et reconstruire la quantité de 4 octets souhaitée de la octets appropriés des deux emplacements. Chercher deux emplacements de mémoire est évidemment plus lent qu'un.

C'est juste pour des charges et des magasins simples, cependant. Certaines instructions, telles que celles des ensembles d'instructions MMX ou SSE, exigent que leurs opérandes de mémoire soient correctement alignées. Si vous essayez d'accéder à la mémoire non alignée en utilisant ces instructions spéciales, vous verrez quelque chose comme une exception d'instruction illégale.

Résumer, je ne m'inquiéterais pas vraiment trop sur l'alignement, à moins que vous n'écrivez à un code Super performance-critique (par exemple en montage). Le compilateur vous aide beaucoup, par exemple. Par les structures de rembourrage afin que les quantités de 4 octets soient alignées sur les limites de 4 octets et sur X86, la CPU vous aide également à sortir lorsqu'il s'agit d'un accès non aligné. Étant donné que les données de pixels que vous avez faites affaire soient en quantités de 3 octets, vous allez presque toujours faire des accès à une octet unique de toute façon.

Si vous décidez que vous décidiez plutôt que vous souhaitez accéder à des pixels dans des accès singuliers de 4 octets (par opposition à 3 accès à 1 octet), il serait préférable d'utiliser des pixels de 32 bits et de disposer de chaque pixel individuel aligné sur un 4 octet. frontière. Alignement de chaque rangée à une limite de 4 octets mais chaque pixel n'aura pas peu, le cas échéant, effet.

Basé sur votre code, je suppose que c'est lié à la lecture du format de fichier Windows bitmap - Les fichiers bitmap nécessitent que la longueur de chaque ligne de numérisation soit un multiple de 4 octets, ce qui permet de configurer vos tampons de données de pixels avec cette propriété a la propriété que vous pouvez simplement lire dans l'ensemble du bitmap d'une fois tombé dans votre tampon (bien sûr, vous devez toujours faire face au fait que les lignes de numérisation sont stockées de bas en haut au bas et que le Les données de pixels sont BGR au lieu de RVB). Ce n'est pas vraiment un avantage, cependant - ce n'est pas si plus difficile à lire dans le bitmap une ligne de scanne à la fois.


0 commentaires

1
votes

L'alignement de la mémoire tampon a un impact. La question est la suivante: est-ce un impact significatif? La réponse peut être fortement Application spécifique . Dans les architectures qui ne prennent pas de manière native l'accès non aligné - par exemple, les 68000 et 68010 (le 68020 ajoute un accès non aligné) -Il est vraiment un problème de performance et / ou de maintenance, car la CPU va défaut, ou peut-être piéger à un gestionnaire pour effectuer un accès non aligné. .

L'alignement idéal pour divers processeurs peut être estimé: l'alignement de 4 octets est approprié pour les architectures avec une trajectoire de données 32 bits. Alignement de 8 octets pour 64 bits. Cependant, l1 La mise en cache a un effet . Pour de nombreux processeurs, il s'agit de 64 octets, mais il ne changera aucun doute à l'avenir.

Trop élevé d'un alignement (c'est-à-dire huit octets où seulement deux octets sont nécessaires) ne provoque aucune inefficacité de la performance pour tout système plus étroit, même sur un microcontrôleur 8 bits. Il déteste simplement (potentiellement) quelques octets de stockage.

Votre exemple est plutôt particulier: les éléments de 3 octets ont une chance de 50% d'unaligné individuellement (à 32 bits), ainsi aligner le tampon semble inutile au moins pour des raisons de performances. Cependant, dans le cas d'un transfert en vrac du tout, il optimise le premier accès. Notez qu'un premier octet non aligné peut également avoir un impact sur la performance dans le transfert à un contrôleur vidéo.


0 commentaires