Comment est un vecteur de données alignées?
Si je veux traiter des données dans un std::vector
avec l'ESS, j'ai besoin de 16 octets de l'alignement. Comment puis-je y parvenir? Dois-je écrire mon propre allocateur? Ou le défaut de l'allocateur déjà aligner sur 16 octets limites?
En C++11, il y a un
double possible de l'ESS et C++ récipients
voir C++ STL structure de données de l'alignement, de l'algorithme de vectorisation
aligned_storage
. Peut-être il y a également un aligned_allocator
? Lemme vérifier.double possible de l'ESS et C++ récipients
voir C++ STL structure de données de l'alignement, de l'algorithme de vectorisation
OriginalL'auteur fredoverflow | 2011-12-10
Vous devez vous connecter pour publier un commentaire.
C++ standard nécessite des fonctions d'allocation (
malloc()
etoperator new()
) à allouer la mémoire correctement alignés pour tout standard type. Comme ces fonctions ne recevez pas l'alignement exigence comme argument, en pratique, cela signifie que l'alignement de toutes les allocations est le même et l'alignement d'un type standard, avec la plus grande exigence d'alignement, qui est souventlong double
et/oulong long
(voir boost max_align de l'union).Vecteur des instructions, telles que l'ESS et AVX, ont une plus grande harmonisation des exigences (16 octets aligné sur 128 bits d'accès et de 32 octets aligné pour un total de 256 bits d'accès) que celui qui est prévu par la norme C++ des fonctions d'allocation.
posix_memalign()
oumemalign()
peut être utilisé pour répondre à ces allocations avec une plus grande harmonisation des exigences.OriginalL'auteur Maxim Egorushkin
Vous devez utiliser un allocateur personnalisé avec
std::
récipients, tels que desvector
. Ne me souviens pas qui a écrit le suivant, mais je l'ai utilisé pendant un certain temps et il semble fonctionner (vous pourriez avoir à changer_aligned_malloc
à_mm_malloc
, selon compilateur/plate-forme):L'utiliser comme ceci (modifier le 16 à l'autre de l'alignement, si nécessaire):
Ceci, cependant, ne permet de s'assurer que le bloc de mémoire
std::vector
utilise est de 16 octets alignés. Sisizeof(T)
n'est pas un multiple de 16, certaines de vos éléments ne seront pas alignés. En fonction de votre type de données, cela pourrait être un non-problème. SiT
estint
(4 octets), charge uniquement les éléments dont l'index est un multiple de 4. Si c'estdouble
(8 octets), seuls les multiples de 2, etc.La vraie question est de savoir si vous utilisez des classes comme
T
, dans ce cas, vous devrez spécifier votre alignement exigences de la classe elle-même (encore une fois, selon le compilateur, ce pourrait être différent; l'exemple est pour GCC):Nous avons presque terminé! Si vous utilisez Visual C++ (au moins, la version de 2010), vous ne serez pas en mesure d'utiliser un
std::vector
avec des classes dont le tracé que vous avez spécifié, en raison destd::vector::resize
.Lors de la compilation, si vous obtenez l'erreur suivante:
Vous devrez pirater votre
stl::vector header
fichier:vector
fichier d'en-tête [C:\Program Files\Microsoft Visual Studio 10.0\VC\include\vecteur]void resize( _Ty _Val )
méthode [en ligne de 870 sur VC2010]void resize( const _Ty& _Val )
.Être averti que le "hack", présenté à la fin pourrait apporter de vrais bugs concernant la durée de vie de l'objet référencé. par exemple,
vector<T> v(1); v.resize(v[0]);
était légal avec le laissez-passer-par-valeur de paramètre. Après la modification d'une référence, il peut être rompu.OriginalL'auteur user1071136
Au lieu d'écrire votre propre allocateur, comme proposé avant, vous pouvez utiliser
boost::alignement::aligned_allocator
pourstd::vector
comme ceci:OriginalL'auteur Dev Null
Écrire votre propre allocateur.
allocate
etdeallocate
sont les plus importantes. Voici un exemple:intptr_t
(qui est la garantie d'avoir la taille d'un pointeur) au lieu deint
et de supprimer ceINT_MAX
(la taille est très probablement non signé de toute façon).c'est juste une idée sur comment résoudre le problème. Je peux expliquer mieux avec C/C++ tandis que le reste de falks sont juste les commentaires. C'est pourquoi j'ai écrit ça. Fred est le seul qui sait exactement comment se qu'il va le résoudre. J'espère que cela va le conduire dans la bonne direction.
Même si je comprends votre argument, il n'est pas difficile de tourner ce code dans quelque chose de plus robuste avec juste quelques changements qui ne le rendra pas plus compliqué. Mais tu as mon +1.
OriginalL'auteur moose
Réponse Courte:
Si
sizeof(T)*vector.size() > 16
alors Oui.en Supposant que vous vecteur utilise des allocateurs
Mise en garde: tant Que
alignof(std::max_align_t) >= 16
comme c'est le max d'alignement.Réponse Longue:
Mise à jour le 25/Août/2017 nouvelle norme n4659
S'il est aligné pour ce qui est de plus de 16 ans, il est également aligné correctement pour 16.
6.11 Alignement (Paragraphe 4/5)
new et new[] valeurs de retour sont alignés de sorte que les objets sont correctement alignés pour leur taille:
8.3.4 Nouveau (paragraphe 17)
Remarque la plupart des systèmes de disposer d'un maximum d'alignement. La mémoire allouée dynamiquement n'a pas besoin d'être alignés sur une valeur supérieure à ce.
6.11 Alignement (paragraphe 2)
Donc tant que vecteur de la mémoire allouée est de plus de 16 octets il est correctement aligné sur 16 octets limites.
La norme C++: stackoverflow.com/a/4653479/14065
Et pourtant
std::vector<__m256>
sera erreur de segmentation sur la plupart des implémentations en raison de l'utilisationvmovaps
charges/magasins qui nécessitent de 32 octets de l'alignement sur la mémoire de seulement 16 octets (ou moins) alignés. SIMD vecteurs ne sont pas considérés comme fondamentaux types, de sorte quenew
ne revient pas en mémoire aligné assez pour les tenir, sur les x86 C++ implémentations. Dans certaines implémentations (surtout 32 bits),new
ne renvoie 8B-alignés de la mémoire, et mêmestd::vector<__m128>
est en défaut.Ajout d'un avertissement pour vous. Maintenant, vous pouvez obtenir les conteneurs standard pour s'aligner sur d'autres valeurs à l'aide de
aligned_storage
Voir: en.cppreference.com/w/cpp/types/aligned_storageErr,
std::aligned_storage
est juste un tampon. L'exemple il met en œuvre un conteneur sur le dessus de celui-ci (avec la matrice de stockage en tant que membre de tableau, pas allouée dynamiquement). Il n'y a pas de moyen évident pour obtenir des conteneurs standard de l'utiliser pour quoi que ce soit. L'exemple de la mise en œuvre", dit-il pourrait simplement être construit au-dessus dealignas
, ce qui n'aide pas avec le stockage dynamique.OriginalL'auteur Martin York
Utilisation
declspec(align(x,y))
comme expliqué dans la vectorisation tutoriel pour Intel, http://d3f8ykwhia686p.cloudfront.net/1live/intel/CompilerAutovectorizationGuide.pdfOriginalL'auteur octoback
Ne présumez de rien à propos de conteneurs STL. Leur interface/comportement est défini, mais pas ce qui est derrière eux. Si vous avez besoin d'un accès brut, vous devrez écrire votre propre mise en œuvre qui suit les règles que vous aimeriez avoir.
-1 vecteur de nouveaux usages qui a garantit à propos de l'alignement.
Loki: je suis plutôt d'assurer que les normes les plus anciennes n'ont pas le définir pour les vecteurs (comme Simon suggère). Aussi, juste à cause de la nouvelle de garder l'adresse de base aligné, ne signifie pas que tous les éléments suivants sont alignés (par exemple en raison de la longueur, l'emballage, etc.).
En fait, en relisant la question, ce n'est pas vraiment claire, si l'OP veut accéder à tous les éléments grâce à un pointeur de déplacement ou veut simplement passer chaque élément à certains de l'ESS appel. Dans le dernier cas, sûr, vous avez raison au sujet de l'alignement.
Loki: std::vector ne pas utilisation de nouveaux il utilise le fourni allocateur par défaut std::allocator.
OriginalL'auteur Mario
La Norme mandats que
new
etnew[]
renvoyer des données alignées pour tout type de données, qui devrait inclure l'ESS. Si oui ou non MSVC suit effectivement que la règle est une autre question."ce qui devrait inclure l'ESS" - mais n'a généralement pas. Dernière, j'ai vérifié, à la fois Windows et Linux uniquement garanti 8-l'alignement de la mémoire allouée, et ni MSVC, ni de la glibc n'a rien à accroître l'alignement. Je crois que la belette-le libellé est que, depuis l'ESS activités sont non-standard, ils peuvent avoir n'importe quel comportement de l'opérateur choisit, dont il est indéfini pour effectuer l'ESS ops sur la mémoire qui n'est pas 16-alignés. Vous pouvez magasin étendue de l'ESS types 8-alignés de la mémoire, de sorte que la lèvre service est payé à la norme, mais dans la pratique, vous devez le lire ne pas appliquer à des non-types standard.
Vraiment pour aucun type? Donc, si je suis venu avec un type de données qui doit 4096-alignement qui serait pris en charge, trop? Bien entendu, cet exemple est de la foutaise, mais j'espère que vous voyez que le aucun est un peu égaré. Je suppose que c'est standard type, à laquelle je suis assez sûr de l'ESS types n'appartiennent pas que le C++ standard ne fait aucune mention de l'ESS.
Il signifie que toute l'alignement d'une exigence imposée par la mise en œuvre sur un type. Oui, vous pouvez écrire une bibliothèque qui prend un
char*
ouMYTHING*
pointeur de paramètre, et vérifie si le pointeur est de 4096-alignés, et les abandons, les lancers, ou fait quelque chose d'indéfini, si elle n'est pas. Cela ne signifie pas quechar
ouMYTHING
a 4096 alignement de l'obligation au sens de la norme. Je pense que la norme n'a l'intention que aucun alignement d'une exigence imposée par la mise en œuvre serait assurée par unmalloc
etnew
, mais les responsables de l'implémentation jugé irréalisable en raison de l'espace perdu.Et il signifie aucun type dans le sens que
struct {char c; long long ll; };
est un type, il n'est pas un type standard, mais la norme garantit que la mémoire retourné à partir demalloc
ounew
(et qui est assez grande, dans le cas denew
) est suffisamment harmonisées pour les stocker. Ils pourraient avoir exprimé cela en disant quemalloc
/new
mémoire de retour alignés pour tout type standard, et que les types d'objet n'impliquant que des types standard n'ont jamais l'alignement exigence plus grande que celle d'au moins un type standard. Mais il n'est pas exprimé de cette façon.OriginalL'auteur Puppy