9
votes

Comment obtenir des blocs avec un grand alignement?

Pour éviter de maintenir des structures de données complexes, je souhaite attribuer des blocs avec un alignement assez important (disons quelques kilo-octets, éventuellement mégaoctets, toujours au pouvoir de deux). Cela me permet de masquer les bits inférieurs d'un pointeur pour extraire facilement l'adresse du début du bloc pointage.

J'aimerais qu'une méthode garantissait la répartition d'un tel bloc avec un alignement spécifié, par exemple. Pour allouer des blocs d'octets 4096 avec une alignement de 4096 octets. Pour que la méthode fonctionne, l'alignement sera toujours la taille des blocs. Les déchets de mémoire devraient donc être une préoccupation à long terme.

J'utilise C ++ (SO C et C ++ Techniques sont corrects) et toute solution doit être portable sur des environnements de bureau courants. Il n'ya pas de solution portable, Linux a la plus haute priorité.

Je suis au courant de Allocation de mémoire Win32 avec un grand alignement , mais S'il y a une bibliothèque Conique C, qui le fait avec un appel de fonction, je l'utiliserais volontiers.

arrière-plan: J'expérimente les structures de vlist décrites Il (but ultime est une sorte de l'interprète de régime), et je suis actuellement en train de mettre en œuvre la collecte des ordures pour ces listes. J'ai besoin des blocs de mémoire assez gros comme des arènes pour le collecteur des ordures. Devrais-je changer la technique du GC, j'ai toujours besoin que les blocs de vlist doivent avoir une alignement de 32 octets (j'effectue mes expériences sur des machines 64 bits).


9 commentaires

@Pubby: pas portable. Je sais à ce sujet, mais j'aimerais connaître des alternatives.


Je ne pense pas que vous allez trouver quelque chose qui est généralement portable.


Vous pouvez toujours rouler le vôtre, bien que cela nécessite des shenanigans.


Avez-vous examiné surcharger les nouveaux opérateurs et supprimer des opérateurs? Vous pouvez le faire au niveau de la classe ou au niveau mondial.


Il ne peut vraiment y avoir rien de "portable", car c ++ ne fait aucune déclaration sur la valeur numérique d'un pointeur. Fondamentalement, réinterpréter un pointeur comme un entier est une opération dépendante de la plate-forme et à partir de votre choix.


@Kerreksb: Je le sais. Dans mon cas, portable doit lire x86 + Linux ou Windows.


La norme C11 a aligné_alloc . Cette interface est un peu différente de posix_memalign en ce qu'elle est moins détaillée dans la déclaration d'erreur si elle échoue. Je suppose que ces pièces sont synchronisées entre C11 et C ++ 11, cela pourrait donc être en C ++ 11, également.


@Alexandrec. Je me demande si vous avez essayé de mesurer la surcharge de la bibliothèque alignée Mallocs des réponses ( POSIX_MEMALIGN , '_mm_malloc ()'). Je ne serai pas surpris du tout s'ils ont également des frais généraux élevés car ils pourraient également être mis en œuvre de la même manière que celle de ma réponse. Dans ce cas, alors probablement la seule solution consiste à écrire votre propre allocator qui fait la comptabilité séparément. (En d'autres termes, ne mettent aucune information méta à côté de la région allouée.) Ce serait le seul moyen d'éviter les grandes frais générales.


@ Mysticial: Les frais généraux seront mesurés une fois que le GC est terminé, car de nombreuses choses ajouteront des frais généraux sur le dessus. J'essaie d'expérimenter les allocateurs mentionnés (celui que vous avez mentionné, et je vais aussi essayer Nedmalloc), et je pense que vous avez raison dans ce que vous dites: allouer des blocs plus importants et les couper en morceaux moi-même est une solution à la mémoire de la mémoire problème, s'il devrait se présenter.


3 Réponses :


1
votes

Blocs de construction de fil d'information Intel dispose d'un allocateur de mémoire évolutif à la plate-forme inter-plate-forme open source avec support pour l'alignement.

void* scalable_aligned_malloc(size_t size, size_t alignment);


1 commentaires

Intéressant et open source.



4
votes

Je ne suis pas au courant d'une solution entièrement portable. Mais < Code> _mm_malloc () et _mm_free () semble être pris en charge par ICC, GCC et MSVC .

Ceci a été ajouté dans le cadre de la prise en charge de la mémoire alignée pour SSE Intrinsics.


Sinon, vous pouvez mettre en œuvre votre propre assez facilement: xxx


4 commentaires

Sauvegarder le pointeur comme celui-ci peut soulever des problèmes de fragmentation Devrais-je commencer à allouer un tas de blocs de 1 Mo. Mais je vais considérer cela une question d'optimisation prématurée. Merci pour le pointeur _mm_malloc / free , cela semble très proche de ce que je veux.


La quantité d'espace gaspillé est align + taille de (intPTR_T) . Je suppose que ce n'est pas trop grave si vous alliez un tas de blocs de 1 Mo avec seulement 4K alignement. Mais si vous allez le faire avec un alignement de 1 Mo, alors oui, c'est environ 50% de surcharge.


Oui, environ la moitié de la mémoire serait gaspillée dans mon cas. Pour le développement, ce n'est pas un problème, mais je devrais finalement faire face à la question.


Venez penser à cela, vous êtes (presque) garanti de perdre la moitié de votre espace d'adresses dans toute mise en œuvre. Mais je suppose que celui qui fonctionne avec le VM à un niveau bas ne perdra pas plus d'une page par allocation.



1
votes

Un alignement important efficace qui est portable est vraiment possible sans utiliser des appels système, auquel cas vous pouvez simplement créer un wrapper autour de virtualalloc et MMAP , cela vous donnerait la page Alignement de niveau, généralement 64 Ko.

Mais si vous n'avez besoin que de 32 octets, copiez simplement la source de Windows CRT pour aligner MALLOC et gratuitement, son support par Standard MALLOC et doit être parfaitement portable (même mieux serait la version GLIBC). Sinon, vous pouvez regarder dans une alloueur personnalisée comme Nedmalloc


1 commentaires

Nedmalloc semble bien. Merci.