La question suivante est liée, mais les réponses sont anciennes, et le commentaire de l'utilisateur Marc Glisse suggère qu'il existe de nouvelles approches depuis C ++ 17 à ce problème qui pourraient ne pas être discutées de manière adéquate.
J'essaie de faire fonctionner correctement la mémoire alignée pour SIMD, tout en ayant accès à toutes les données.
Sur Intel, si je crée un vecteur flottant de type __m256
et que je réduis ma taille d'un facteur 8, cela me donne une mémoire alignée.
Par exemple std::vector<__m256> mvec_a((N*M)/8);
D'une manière légèrement hacky, je peux lancer des pointeurs sur des éléments vectoriels à flotter, ce qui me permet d'accéder aux valeurs flottantes individuelles.
Au lieu de cela, je préférerais avoir un std::vector<float>
qui est correctement aligné, et donc peut être chargé dans __m256
et d'autres types SIMD sans segfaulting.
J'ai cherché dans align_alloc .
Cela peut me donner un tableau de style C correctement aligné:
auto align_sz = static_cast<std::size_t> (32);
float* marr_a = (float*)aligned_alloc(align_sz, N*M*sizeof(float));
Cependant, je ne sais pas comment faire cela std::vector<float>
. Donner la std::vector<float>
propriété de marr_a
ne semble pas être possible .
J'ai vu quelques suggestions que je devrais écrire un allocateur personnalisé , mais cela semble beaucoup de travail, et peut-être qu'avec le C ++ moderne, il y a une meilleure façon?
_mm256_loadu_ps(&vec[i])
. (Bien que notez qu'avec les options de réglage par défaut, GCC divise les charges / magasins 256 bits alignés non garantis en vmovups xmm / vinsertf128. Il y a donc un avantage à utiliser_mm256_load
overloadu
si vous vous souciez de la façon dont votre code se compile sur GCC si quelqu'un oublie de utilisation-mtune=...
ou-march=
options.)Réponses:
Tous les conteneurs de la bibliothèque C ++ standard, y compris les vecteurs, ont un paramètre de modèle facultatif qui spécifie l'allocateur du conteneur , et ce n'est pas vraiment beaucoup de travail d'implémenter le vôtre:
Vous devrez écrire un peu de code qui implémente votre allocateur, mais ce ne serait pas beaucoup plus de code que vous ne l'avez déjà écrit. Si vous ne avez pas besoin pré-C ++ 17 soutien dont vous avez seulement besoin de mettre en œuvre les allouer () et deallocate () méthodes, c'est tout.
la source
allocator_traits
vector<float, MAA>
n'est pas compatible avec le typevector<float>
(et ne peut pas être parce que tout ce qui fait.push_back
sur un simplestd::vector<float>
compilé sans cet allocateur pourrait faire une nouvelle allocation et copier dans la mémoire à alignement minimal. Et new / delete n'est pas compatible avec align_alloc / free)std::vector
tableau de. Par exemple, je pourrais imaginer une implémentation de l'std::vector
utilisation d'un seul pointeur vers la mémoire allouée qui stocke la fin / capacité / allocateur dans la mémoire avant la plage de valeurs. Cela pourrait facilement déjouer l'alignement effectué par l'allocateur.std::vector
ça le garantit. C'est pour ça qu'il l'utilise. Vous devriez peut-être revoir ce que la norme C ++ spécifie ici.allocator_traits
- Non, ils ne le font pas. Il suffit d'implémenter un allocateur conforme.