web-dev-qa-db-fra.com

Alignement de la mémoire: comment utiliser alignof / alignas?

Je travaille avec la mémoire partagée en ce moment.

Je ne comprends pas alignof et alignas.

cppreference n'est pas clair: alignof renvoie "alignement" mais qu'est-ce que "alignement"? nombre d'octets à ajouter pour que le bloc suivant soit aligné? taille rembourrée? Débordement de pile /les entrées de blogs ne sont pas claires non plus.

Quelqu'un peut-il expliquer clairement alignof et alignas?

57
Offirmo

L'alignement est une restriction sur laquelle les positions de mémoire du premier octet d'une valeur peuvent être stockées. (Il est nécessaire d'améliorer les performances des processeurs et de permettre l'utilisation de certaines instructions qui ne fonctionnent que sur des données avec un alignement particulier, par exemple SSE doit être aligné sur 16 octets, tandis que AVX sur 32 octets) .)

L'alignement de 16 signifie que les adresses de mémoire qui sont un multiple de 16 sont les seules adresses valides.

alignas

forcer l'alignement au nombre d'octets requis (cppreference ne le mentionne pas, mais je pense que vous ne pouvez vous aligner que sur des puissances de 2: 1, 2, 4, 8, 16, 32, 64, 128, ...)

#include <cstdlib>
#include <iostream>

int main() {
    alignas(16) int a[4];
    alignas(1024) int b[4];
    printf("%p\n", a);
    printf("%p", b);
}

exemple de sortie:

0xbfa493e0
0xbfa49000  // note how many more "zeros" now.
// binary equivalent
1011 1111 1010 0100 1001 0011 1110 0000
1011 1111 1010 0100 1001 0000 0000 0000 // every zero is just a extra power of 2

l'autre mot-clé

alignof

est très pratique, vous ne pouvez pas faire quelque chose comme

int a[4];
assert(a % 16 == 0); // check if alignment is to 16 bytes: WRONG compiler error

mais tu peux faire

assert(alignof(a) == 16);
assert(alignof(b) == 1024);

notez qu'en réalité c'est plus strict qu'une simple opération "%" (module). En fait, nous savons que quelque chose aligné sur 1024 octets est nécessairement aligné sur 1, 2, 4, 8 octets mais

 assert(alignof(b) == 32); // fail.

Pour être plus précis, "alignof" renvoie la plus grande puissance de 2 à laquelle quelque chose est aligné.

Aussi alignof est une belle façon de connaître à l'avance l'exigence d'alignement minimum pour les types de données de base (il retournera probablement 1 pour les caractères, 4 pour le flottant, etc.).

Toujours légal:

alignas(alignof(float)) float SqDistance;

Quelque chose avec un alignement de 16 sera alors placé sur la prochaine adresse disponible qui est un multiple de 16 (il peut y avoir un remplissage implicite de la dernière adresse utilisée).

63
GameDeveloper

L'alignement n'est pas un remplissage (bien que le remplissage soit parfois introduit pour satisfaire aux exigences d'alignement). Il s'agit d'une propriété intrinsèque de type C++. Pour le mettre en standard (3.11[basic.align])

Les types d'objets ont des exigences d'alignement (3.9.1, 3.9.2) qui imposent des restrictions sur les adresses auxquelles un objet de ce type peut être attribué. Un alignement est une valeur entière définie par l'implémentation représentant le nombre d'octets entre des adresses successives auxquelles un objet donné peut être alloué. Un type d'objet impose une exigence d'alignement à chaque objet de ce type; un alignement plus strict peut être demandé à l'aide du spécificateur d'alignement (7.6.2).

7
Cubbi

Chaque type a une exigence d'alignement. Généralement, cela permet aux variables du type d'être accessibles efficacement, sans avoir à obliger le CPU à générer plus d'un accès en lecture/écriture afin d'atteindre un membre donné du type de données. En outre, il assure également une copie efficace de la variable entière. alignof renverra l'exigence d'alignement pour le type donné.

alignas est utilisé pour forcer un alignement sur un type de données (tant qu'il n'est pas moins strict que ce que alignof ledit type de données retournerait)

4
levengli