Je travaille sur une piscine mémoire pour un petit moteur de jeu. P>
L'utilisation principale sera sous forme de stockage distinct; Une piscine contient un objet d'un type et d'une taille spécifiques. Actuellement, les piscines peuvent être utilisées pour stocker quoi que ce soit, mais les allocations seront effectuées en blocs d'une taille spécifique. La plupart des besoins de la mémoire seront attribués à la fois, mais «la prolifération» peut être activé si nécessaire pour faciliter le réglage (taille presque fixe). P>
Problème est que j'ai commencé à obtenir un peu paranoïaque lors de la contemplation de l'alignement de la mémoire. Je n'ai utilisé que la gestion de la mémoire brute sur les processeurs 8 bits où tout est aligné sur des octets. P>
Je laisse l'utilisateur (moi) spécifier la taille souhaitée des blocs, qui dans le boîtier de stockage distinct serait la taille des objets que je vais stocker. p>
L'approche actuelle consiste à allouer une pièce de mémoire Que dois-je envisager en ce qui concerne l'alignement de la mémoire dans mon scénario? P>
La réponse que j'ai proposée jusqu'à présent est que tant que n est quelle que soit la limite requise par la plate-forme. Je vis me ciblant x86 pour le moment, mais je n'aime pas faire d'hypothèses sur la plate-forme de mon code. Em> p>
Certaines des ressources que j'ai utilisées: p>
Téléchargé un petit code de petit code qui peut aider n'importe qui aussi confus que moi dans le futur ici . P> blocs * (souhaité_size + header_size) code> gros et placez les objets dedans, avec un en-tête pour chaque bloc; Les objets seraient évidemment positionnés directement derrière cet en-tête. P>
souhaité_size code> représente les données alignées n em> -byte; L'en-tête est correctement aligné et emballé par le compilateur ainsi que les données réelles, tout stocké dans le bloc sera n em> -byte aligné. P>
5 Réponses :
Votre compilateur alignera déjà les membres d'objets et de structures qui seront stockés dans la piscine. En utilisant l'emballage par défaut qui convient à votre architecture, généralement 8 pour un noyau 32 bits. Il vous suffit de vous assurer que l'adresse que vous générez de votre piscine est alignée en conséquence. Qui sur un système d'exploitation de 32 bits devrait être un multiple de 8 octets. p>
Mauvaise alignement Les objets peuvent être très coûteux lorsqu'ils traversent une limite de la ligne de cache de la CPU. Un double qui chevauche deux lignes de cache prend autant que trois fois moins de lecture ou écrit. P>
En fait, le compilateur n'allonge pas nécessairement aux membres. Par exemple, l'alignement de la VC ++ est soumis à #pragma pack code> option ou
/ zp code> option. Code qui concerne les tampons IO (réseau, disque) fréquemment des forces
#pragma pack (1) code> pour compacter les données sur disque ou sur fil. Et il y a plus d'options pour contrôler l'alignement, comme
__ DeclSpec (align) code>, msdn.microsoft.com/en-us/library/2e70t5y1%28vs.80%29.aspx msdn.microsoft.com/en-us/library/83ythb65%28V=VS.100%29.aspx a>
Soupir, oui, vous pouvez le remplacer. L'hypothèse implicite est que vous savez ce que vous faites quand vous faites. Nous n'aurions pas cette question si le OP le savait déjà.
Le compilateur aligne toujours les membres. La seule chose est que vous puissiez le remplacer pour aligner différemment. Ce n'est pas la même chose que ne les alignant pas.
J'étais en fait conscient que vous pouviez changer l'emballage, mais que HANS suppose correctement que je suis beaucoup trop inexpérimenté dans ces questions pour comprendre les ramifications de cette utilisation. Merci pour la réponse, je vais devoir attendre pour pouvoir uppoter si (a été généreux aujourd'hui :))
Cela ne concerne pas l'emballage, il s'agit de l'adresse que vous générez depuis la piscine.
Hans Passant: Désolé, j'ai mal compris.
Allocations avec Le danger est que votre en-tête a une plus petite exigence d'alignement que la condition d'alignement maximale de votre implémentation. Ensuite, sa taille pourrait ne pas être un multiple du max. alignement, et donc lorsque vous essayez de lancer / utiliser Il y a essentiellement trois astuces que je suis au courant de vous assurer que votre en-tête ne cause pas de désalignement: p>
Alternativement, vous pouvez simplement définir [*] avec une exception commune étant des types SIMD sur la taille supérieure. Depuis qu'ils sont non standard, et il serait inutile de 16 aligner toutes les allocations à peine à cause d'eux, ils ont fait de côté à la main, et vous avez besoin de fonctions d'allocation spéciales pour eux. P> MALLOC CODE> est garantie pour être aligné pour tout type fourni par le compilateur et donc n'importe quel objet [*]. P>
buf + header_size code> comme un pointeur sur quelque chose qui fait em> a le max. alignement, il est mal aligné. Aussi loin que C est concerné, c'est un comportement indéfini. Sur Intel ça marche mais est plus lent. Sur certains bras, cela provoque une exception matérielle. Sur certains bras, il donne silencieusement la mauvaise réponse. Donc, si vous ne voulez pas faire des hypothèses sur la plate-forme de votre code, vous devez y faire face. P>
int code> en tant que rembourrage si nécessaire pour en faire un 8 multiple plutôt que juste un 4-multiple". Li>
Union code> de chaque type standard, ainsi que la structure que vous souhaitez réellement utiliser. Fonctionne bien en C, mais vous auriez des problèmes dans C ++ si votre en-tête n'est pas valable pour l'adhésion des syndicats. Li>
ul>
en-tête_size code> ne pas être
Tailleof (en-tête) CODE>, mais pour être cette taille arrondie à un multiple d'une puissance chunky de 2 qui est " assez bien". Si vous perdez un peu de mémoire, alors soyez-le, et vous pouvez toujours avoir un «en-tête de portabilité» qui définit ce genre de chose d'une manière qui n'est pas purement indépendante de la plate-forme, mais facilite l'adaptation à de nouvelles plateformes. p>
Peut-on aussi ajouter que la même chose est vraie avec toutes les fonctions d'allocation (donc :: opérateur neuf code> et kin.)
Merci d'avoir répondu. Comment déterminer le max. alignement d'un type? Si j'ai bien compris votre deuxième paragraphe - Supposons X86 ici pour la simplicité - cela signifie que si l'en-tête est de 4 octets, il s'agira de 4 octets alignés et que les données sont de 8 octets importants, 8 octets seront alignés. Cela signifie que j'ai besoin d'en-tête de patin avec 4 octets pour rendre les données correctement alignées, correctes?
J'ai pensé à votre proposition "assez bonne", cela semble pragmatique; J'aime pragmatique. Comment savoir ce qui est assez bon, cela permettrait-il simplement que l'en-tête est aligné sur le max. Alignement de la plate-forme ou dépendrait-il de la taille réelle des données stockées (le rendant moins souhaitable)?
Chaque type sur une plate-forme donnée a un alignement imposé par le compilateur (au moins, dans les cas où aucun pragma ou attribut d'emballage n'indique le contraire). Vous devez savoir quels sont ces alignements et trouver le plus grand. L'allocation i>, et donc l'en-tête elle-même puisque vous le placez au début de l'allocation, aura cet alignement. Le suivant octet après i> L'en-tête aura cet alignement maximum si (et seulement si) la taille de l'en-tête est un multiple du max. alignement.
En ce qui concerne "assez bon" - la taille du plus gros type sur votre plate-forme est "assez bonne", car rien ne peut avoir une condition d'alignement plus grosse que sa taille.
Merci, je pense que je saisis cela maintenant. Cela signifierait que si l'alignement maximum de la plate-forme était 8, mais l'en-tête occupait quelque chose comme 14 octets, je supposerais simplement que l'en-tête était de 16 octets importants, car cela positionnait correctement les données du bloc.
C'est vrai: laissez 16 octets pour cela, dont il occupera 14 et les 2 autres sont inutilisés. Bien qu'il soit improbable que votre tête ait une taille 14, car elle aura probablement quelque chose qui nécessite un alignement 4, de sorte que la taille doit être un multiple de 4. C'est 12 que vous voulez vraiment regarder et arrondir.
Merci pour l'aide, j'aurais dû tout ce que je dois faire au moins le cas de l'utilisation de base fonctionne maintenant.
Utilisez http://msdn.microsoft.com/en-us/ Bibliothèque / BB982233.ASPX - STD :: Alignment_of. Cela garantit que, pour chaque t, vous allez dans votre piscine, vous connaîtrez l'alignement et vous assurera que cela convient. Je ne vais pas prétendre savoir / comprendre la logique réelle que vous utiliseriez pour effectuer ces informations en garanties d'alignement, mais elle existe et est disponible pour une utilisation. P>
Merci pour la réponse, il sera probablement utile.
Aussi loin que je sache Boost :: La piscine est basée sur "l'allocator des petits objets" d'Alexandrescu, expliqué dans son livre "Moderne C ++ Design". Je dois lire le livre (puisque vous écrivez ce produit pour apprendre aussi) P>
Merci, va voir si je peux l'acheter comme un livre électronique quelque part.
J'ai aussi frappé d'alignement de la mémoire. La première chose à comprendre est que chaque objet a ses propres exigences d'alignement de la mémoire, qui est (au plus) la taille de l'objet lui-même. Heureusement, il est souvent plus petit.
Il existe des installations de deux types pour aider à écrire des allocateurs de mémoire corrects (C ++ 0x, ils peuvent être trouvés dans Travailler avec les deux d'entre eux, vous obtiendrez ce dont vous avez besoin. p> Cependant, votre conception est légèrement hors base, pas à peu près à l'esprit, car votre en-tête n'aura pas la même exigence d'alignement (en général) que les objets stockés. p> deux notes: p> Enfin, vous pouvez également réussir sans toutes ces personnes, et un pointeur arithmétique, mais depuis sa proposition ... P> P> STD :: TR1 CODE> Dans la plupart des STL): P >
std :: alignment_of code> donne l'alignement comme une valeur de compilation li>
std :: aligné_storage code> donne un stockage aligné en fonction de ses paramètres li>
ul>
block code> peut avoir un alignement différent, mais peu importe li>
Tailleof code> pour l'alignement, il est garanti de fonctionner, même si un peu gaspillé li>
ul>
Merci pour la réponse, celles-ci ressemblent à elles seront utiles. Bien que je pense que je puisse passer dans l'alignement plutôt que je voudrais garder la piscine non spécifique de type; Mais cela signifie seulement que je vais utiliser Alignment_of ailleurs.
Les choses se compliquent un peu plus si vous allez la route générique, à cause de la fragmentation. N'hésitez pas à créer un pool de premier type (ou au moins spécifique d'alignement) puis enveloppez-le avec un générique qui gère simplement une collection d'entre eux.
Matthieu, une bonne idée. Éviter la fragmentation était l'un des points d'avoir une piscine en première place depuis que je soupçonne que je disposerai d'une quantité assez massive d'allocations mineures.