9
votes

Une grande piscine ou plusieurs piscines spécifiques à plusieurs types?

Je travaille sur un jeu vidéo nécessitant des performances élevées, alors j'essaie de configurer une bonne stratégie de mémoire ou une partie spécifique du jeu, la partie qui est le jeu "modèle", la représentation du jeu.

J'ai un objet contenant une représentation de jeu entière, avec différents gestionnaires à l'intérieur pour conserver la représentation cohérente, après les règles de jeu. Chaque entité de jeu est actuellement générée par une usine spécifique à un type, j'ai donc plusieurs usines qui me permettent d'isoler et de modifier la gestion de la mémoire de ces entités que je souhaite.

Maintenant, je suis en train de choisir entre ces deux alternatives:

  1. Avoir un pool de mémoire pour chaque type : qui permettra une répartition / distribution réellement rapide et une fragmentation minimale en tant que pool d'objets connaissant déjà la taille des objets alloués. Une chose qui me dérange est d'avoir plusieurs piscines comme celle qui sont séparées, peut-être rendre l'autre solution plus efficace ...
  2. avoir un gros pool de mémoire partagée par toutes les usines de la représentation d'une partie : (Utiliser quelque chose comme Boost :: Piscine avec quelques fonctions de l'adaptateur) De cette façon, j'ai tous les objets de jeu de la mémoire allouée ensemble et peut avoir une allocation un peu pour un jeu que je connais déjà la taille totale (ce n'est pas toujours le cas). Je ne suis pas sûr que ce soit une solution meilleure que celle d'une fragmentation possible à l'intérieur de la piscine, car il y aurait des objets de taille différente dans la même piscine, mais cela ressemble à une analyse de mémoire facile et d'autres problèmes de résolution de problèmes.

    Maintenant, j'avais des expériences de mondes réelles avec le A donc je ne suis pas expérimenté avec B et que je voudrais des conseils concernant ces solutions, pour un projet à longue durée de vie. Quelle solution semble mieux pour un projet de longue durée et pourquoi? (Remarque: une piscine est vraiment nécessaire dans ce cas car le modèle de jeu est utilisé pour l'édition de jeux aussi, il y aura aussi beaucoup d'allocation / de distribution de petits objets).

    Modifier pour clarification: J'utilise C ++ si (ce n'est pas encore clair)


0 commentaires

6 Réponses :


0
votes

Je n'ai pas d'expérience spécifique avec le gestionnaire de mémoire que vous envisagez, mais voici quelques directives générales qui peuvent aider:

  • Si vous ne vous attendez pas à une pénurie de mémoire, l'option 1 serait la meilleure car, car vous l'indiquez est rapide (plus rapide que 2?), et avoir des piscines séparées faciliteront les problèmes de répartition / de répartition / tampon (en supposant que Le gestionnaire de piscine a des capacités de détection d'erreur décente).
  • Si la mémoire pourrait être un problème (comme dans votre partie, il faut prendre beaucoup de mémoire par rapport à la mémoire courante de la plate-forme cible), une grande piscine fournira une utilisation plus efficace de la mémoire. De plus, si vous ne pouvez pas prédire avec précision les exigences de mémoire moyenne et maximale par piscine, il s'agit d'un meilleur choix que si le gestionnaire de mémoire peut augmenter de manière dynamique les pools de mémoire (et libérer de manière idéale des blocs de libération dynamique de la piscine). Les seuls descentes à 2 que je vois sont qu'il pourrait être plus lent (est-ce le cas?) Et les erreurs de la gestion de la mémoire pourraient être plus difficiles à détecter.

    Vous pourriez avoir le meilleur des deux mondes (en supposant que la vitesse est similaire) en développant plusieurs piscines, mais en faisant des tests finaux et la libération de production avec une seule piscine. De cette façon, vous pouvez repérer les problèmes d'allocation / de gestion au cours du développement, mais profitez toujours de la piscine unique potentiellement plus efficace.


2 commentaires

Lorsque vous dites que 2. Pourrait être plus lent, vous ne voulez pas dire que cela serait plus lent si je n'ai pas plus de 1 allocation / distribution par seconde? (sur un matériel décent) Vous parlez de beaucoup d'allocation / de distribution par secondes?


Je veux dire seulement que 2. pourrait être plus lent s'il utilise une stratégie de gestion de la mémoire différente, ou s'il utilise la même stratégie, mais que la stratégie est sensiblement plus lente si elle gère tous vos objets dans une piscine plutôt que dans des pools séparés. Si vous attendez une allocation / deuxièmement, c'est très qu'il y aura une différence de préoccupation rapide.



2
votes

Une des solutions possibles est quelque chose entre 1. et 2.

Utilisez des pools pour petits objets: une piscine par taille d'objet. Dans ce cas, vous pouvez trouver facilement la piscine en stockant des pointeurs dans le tableau.

Et en outre, vous pouvez avoir un pool pour les gros objets. Dans ce cas, la fragmentation est moins probable et la tenue de temps n'est pas si critique car les objets importants ne sont pas alloués et traités très fréquemment.

Note sur Boost :: Piscine . Lorsque vous testez la performance de boost :: piscine , test non seulement l'attribution, mais également la classique. J'ai vécu que boost :: piscine et boost :: fast_pool Le temps de distribution peut être extrêmement grand. Mon cas était composé d'allocations et de désaffecations de petits objets de différentes tailles dans une piscine


0 commentaires

10
votes

La bonne réponse est spécifique à votre domaine problématique. Mais dans les domaines de problèmes que je travaille, le premier est généralement celui que nous choisissons.

Je fais du code en temps réel ou proche de temps réel. Édition audio et lecture surtout. Dans ce code, nous ne pouvons généralement pas nous permettre d'attribuer la mémoire du tas dans le moteur de lecture. La plupart du temps, Malloc retourne assez vite, mais parfois ça ne le fait pas. Et cela compte parfois.

Nos solutions sont donc d'avoir des pools spécifiques pour certains objets et d'utiliser la piscine générale pour tout le reste. Les piscines spécifiques ont un certain nombre d'éléments préallociés et sont implémentés comme une liste liée (en réalité une file d'attente), de sorte que l'attribution et la libération ne sont jamais plus que quelques mises à jour du pointeur et le coût de la saisie et de la sortie d'une section critique.

comme une replie pour des cas inhabituels; Lorsque quelqu'un doit allouer d'une piscine spéciale et qu'il est vide - nous allouerons un morceau de mémoire générale (plusieurs objets) et ajouterons cela au pool spécial. Une fois qu'une allocation fait partie du piscine spécial, elle n'est jamais revenue à la piscine générale tant que l'application se décharge ni ne commence un nouveau projet.

Faire de bons choix sur la taille initiale et la taille maximale des piscines spéciaux constitue une partie importante de la réglage de l'application.


0 commentaires

4
votes

Un problème que vous rencontrez est que les implémentations STL sont autorisées à supposer que deux allocateurs du même type sont équivalents. C'est la raison pour laquelle Boost.Pool utilise un seul pool (techniquement, il utilise une piscine différente pour chaque type). C'est-à-dire que vos allocateurs ne sont pas autorisés à avoir des membres non statiques dans le cas général. Si vous faites un jeu vidéo et que vous savez que votre implémentation STL n'a pas ce problème, alors ne vous inquiétez pas pour cela - mais il peut y avoir quelques problèmes avec Liste :: Splice et std :: échange sur les conteneurs.


0 commentaires

0
votes

En fait, j'irai avec 2. Je peux vous donner un exemple du noyau Linux. Dans le noyau, la dentry (entrée de répertoire) et les objets Inode doivent être mis en cache en mémoire plus longtemps pour une meilleure réactivité aux utilisateurs. Comme l'objet Inode dépend du système de fichiers, chaque système de fichiers créera son propre pool d'objets. Une autre chose que vous pourriez faire si les objets sont similaires consiste à résumer les objets et à conserver des attributs communs dans un objet abstrait et à stocker les informations spécifiques à l'objet à l'aide d'un conteneur. Reportez-vous au code ci-dessous pour une idée complète.

http://lxr.linux.no /Linux+v2.6.32/fs/ext2/super.c#l149


1 commentaires

Je pense que tu voulais réellement vouloir y aller avec 1? Depuis l'exemple que vous avez donné est en réalité l'option 1 et vous ne l'avez pas critiqué ..



4
votes

Il n'est pas pratique d'utiliser STL ou Boost pour tout type de jeu vidéo, pour commencer. Vous pouvez être absolument sûr que la seconde que vous utilisez un conteneur STL votre mémoire est fragmentée et que vos performances sont désespérément dans les toilettes par rapport à l'idéal au moins (car la plupart du code de chacun se trouve dans cette catégorie, la plupart des gens ne remarquent jamais et ne peuvent pas vraiment comparer à rien d'autre). Je n'ai pas toujours pensé si fort mais au fil du temps, j'ai vu même quelques lignes de code, c'est comme un peu de Gremlin qui finira par un jour de faire une grande douleur.

La première méthode est la plus courante, et comme quelqu'un qui a fait à la fois, c'est probablement le seul moyen qui est pratique si vous ne voulez pas dépenser beaucoup plus de temps et d'énergie sur le problème que cela ne vaut probablement la peine de vous. La deuxième façon est meilleure car il est plus général et pourtant être adapté à vos besoins exacts, mais c'est beaucoup de travail et pas quelque chose à sauter à la légère.


2 commentaires

"Il n'est pas pratique d'utiliser STL ou Boost pour tout type de jeu vidéo, pour commencer." Une telle chose bizarre à dire. Beaucoup de jeux font simplement une simulation de physique simple et brute sur une douzaine d'objets ou des objets à la fois. Certains sont basés sur le tour. Certains sont basés sur le texte. Les jeux peuvent être écrits en Flash ou JavaScript et réussir. Certains beaux jeux populaires utilisent sûrement STL ou Boost. Tout n'est pas "triple-a".


Il est parfaitement réalisable d'utiliser des bibliothèques STL ou Boost pour créer un jeu vidéo AAA. Cette réponse était de 2009 et ne s'applique plus. La bibliothèque moderne C ++ (qui n'est pas équivalente au terme "stl") est très performante et seulement si l'un est paranoïaque ou extrêmement talentueux ou juste curieux voudrait rouler sa propre bibliothèque adaptée spécifiquement à une vidéo Les besoins du jeu.