Pourquoi utiliser _mm_malloc? (par opposition à _aligned_malloc, alligned_alloc ou posix_memalign)

Il existe quelques options pour acquérir un bloc de mémoire aligné, mais elles sont très similaires et le problème se résume principalement au langage standard et aux plates-formes que vous ciblez.

C11

void * aligned_alloc (size_t alignment, size_t size) 

POSIX

 int posix_memalign (void **memptr, size_t alignment, size_t size) 

les fenêtres

 void * _aligned_malloc(size_t size, size_t alignment); 

Et bien sûr, il est également toujours possible d’aligner à la main.

Intel offre une autre option.

Intel

 void* _mm_malloc (int size, int align) void _mm_free (void *p) 

D’après le code source publié par Intel, il semble que ce soit la méthode d’allocation de la mémoire alignée que leurs ingénieurs préfèrent, mais je ne trouve aucune documentation la comparant à d’autres méthodes. Le plus proche que j’ai trouvé reconnaît simplement qu’il existe d’autres routines d’allocation de mémoire alignées.

https://software.intel.com/en-us/articles/memory-management-for-optimal-performance-on-intel-xeon-phi-coprocessor-alignment-and

Pour allouer dynamicment une partie de la mémoire alignée, utilisez posix_memalign, qui est pris en charge par GCC ainsi que par le compilateur Intel. L’avantage de l’utiliser est que vous n’avez pas à changer l’API de disposition de la mémoire. Vous pouvez utiliser free () comme vous le faites toujours. Mais faites attention au profil de paramètre:

int posix_memalign (void ** memptr, size_t align, size_t size);

Le compilateur Intel fournit également un autre ensemble d’API d’allocation de mémoire. Les programmeurs C / C ++ peuvent utiliser _mm_malloc et _mm_free pour allouer et libérer des blocs de mémoire alignés. Par exemple, l’instruction suivante demande un bloc de mémoire aligné sur 64 octets pour 8 éléments à virgule flottante.

farray = (float *) __ mm_malloc (8 * sizeof (float), 64);

La mémoire allouée à l’aide de _mm_malloc doit être libérée à l’aide de _mm_free. Appeler gratuitement sur la mémoire allouée avec _mm_malloc ou appeler _mm_free sur la mémoire allouée avec malloc entraînera un comportement imprévisible.

La différence évidente du sharepoint vue de l’utilisateur est que _mm_malloc nécessite un support direct du processeur et du compilateur et que la mémoire allouée avec _mm_malloc doit être libérée avec _mm_free . Compte tenu de ces inconvénients, quelle est la raison pour laquelle vous _mm_malloc? déjà utilisé _mm_malloc? Peut-il avoir un léger avantage de performance? Accident historique?

Les compilateurs Intel prennent en charge les systèmes d’exploitation POSIX (Linux) et non POSIX (Windows) et ne peuvent donc compter ni sur la fonction POSIX ni sur la fonction Windows. Ainsi, une solution spécifique au compilateur mais indépendante du système d’exploitation a été choisie.

C11 est une excellente solution, mais Microsoft ne prend même pas encore en charge C99. Alors, qui sait s’ils prendront jamais en charge C11?

Mise à jour: Contrairement aux fonctions d’allocation C11 / POSIX / Windows, les éléments insortingnsèques ICC incluent une fonction de désallocation. Cela permet à cette API d’utiliser un gestionnaire de tas distinct de celui par défaut. Je ne sais pas si / quand il le fait, mais il peut être utile de soutenir ce modèle.

Disclaimer: Je travaille pour Intel, mais je n’ai aucune connaissance particulière de ces décisions, sockets bien avant que je ne rejoigne la société.

Il est possible de prendre un compilateur C existant qui n’utilise pas actuellement les identifiants _mm_alloc et _mm_free et de définir des fonctions avec ces noms qui se comporteront comme requirejs. Cela peut être fait soit en ayant _mm_alloc fonction wrapper sur malloc() qui demande une allocation légèrement surdimensionnée et construit un pointeur sur la première adresse alignée de manière appropriée qui _mm_alloc au moins un octet depuis le début, et en stockant le numéro. d’octets sautés juste avant cette adresse ou en _mm_malloc demander de gros morceaux de mémoire à malloc() , puis de les dissortingbuer au coup par coup. Dans tous les cas, les pointeurs renvoyés par _mm_malloc() ne seraient pas des pointeurs avec lesquels free() saurait généralement faire quoi que ce soit avec; appeler _mm_free utiliserait l’octet précédant immédiatement l’allocation pour vous aider à trouver le début réel de l’allocation reçue de malloc , puis passerait cette commande à free .

Si une fonction alignée-allouer est autorisée à utiliser les éléments internes des fonctions malloc et free , cela peut éliminer le besoin d’une couche supplémentaire d’habillage. Il est possible d’écrire des fonctions _mm_alloc() / _mm_free() qui enveloppent malloc / free sans rien connaître de leurs _mm_alloc() internes, mais cela nécessite que _mm_alloc() conserve des informations de comptabilité distinctes de celles utilisées par malloc / free .

Si l’auteur d’une fonction alignée-allocation sait comment malloc et free sont implémentés, il sera souvent possible de coordonner la conception de toutes les fonctions allocation / free afin que free puisse distinguer tous les types d’allocations et les gérer de manière appropriée. Aucune implémentation unique alignée-affectée ne serait utilisable sur toutes free implémentations malloc / free .

Je suggérerais que le moyen le plus portable d’écrire du code serait probablement de sélectionner quelques symboles qui ne sont utilisés nulle part ailleurs pour vos propres fonctions d’allocation et libres, afin que vous puissiez ensuite dire, par exemple:

 #define a_alloc(align,sz) _mm_alloc((align),(sz)) #define a_free(ptr) _mm_free((ptr)) 

sur les compilateurs qui supportent cela, ou

 static inline void *aa_alloc(int align, int size) { void *ret=0; posix_memalign(&ret, align, size); // Guessing here return ret; } #define a_alloc(align,sz) aa_alloc((align),(sz)) #define a_free(ptr) free((ptr)) 

sur les systèmes Posix, etc. Pour chaque système, il devrait être possible de définir des macros ou des fonctions générant le comportement nécessaire [Je pense qu’il est probablement préférable d’utiliser des macros de manière cohérente que d’utiliser parfois des macros et parfois des fonctions, afin de permettre #if defined macroname pour vérifier si les choses sont encore définies].

_mm_malloc semble avoir été créé avant la mise en place d’une fonction alignée_alloc standard, et la nécessité d’utiliser _mm_free est un caprice de l’implémentation.

Mon hypothèse est que, contrairement à posix_memalign, il n’est pas nécessaire de sur-allouer pour garantir l’alignement, il utilise plutôt un allocateur distinct. Cela économisera de la mémoire lors de l’allocation de types avec un alignement différent de l’alignement par défaut (généralement 8 ou 16 octets).