Comment éviter la fragmentation du tas?
Je suis actuellement en train de travailler sur un projet pour le traitement d'images médicales, qui a besoin d'une grande quantité de mémoire. Est-ce que je peux faire pour éviter la fragmentation du segment et de la rapidité de l'accès à des données d'image qui a déjà été chargé dans la mémoire?
La demande a été écrit en C++ et fonctionne sur Windows XP.
EDIT: L'application n'certains prétraitement avec les données de l'image, comme le reformatage, le calcul de look-up tables, extraction des sous-images d'intérêts ... L'application a besoin d'environ 2 GO de RAM en cours de traitement, dont environ 1,5 GO peut être utilisé pour les données d'image.
source d'informationauteur Thomas Koschel
Vous devez vous connecter pour publier un commentaire.
Si vous faites le traitement d'images médicales, il est probable que vous allouez de gros blocs (512x512, 2 octets par pixel des images). La Fragmentation va vous mordre si vous allouer les petits objets entre les dotations de l'image tampons.
L'écriture d'un allocateur personnalisé n'est pas nécessairement difficile pour ce cas d'utilisation. Vous pouvez utiliser le standard C++ allocateur pour votre Image de l'objet, mais pour le pixel de la mémoire tampon, vous pouvez utiliser l'allocation personnalisé qui est géré au sein de votre Image de l'objet. Voici un rapide aperçu:
C'est juste une idée simple, avec beaucoup de place pour la variation. L'astuce principale est d'éviter de libérer et réaffectation de l'image pixel tampons.
Il y a des réponses, mais il est difficile d'être général, sans connaître les détails du problème.
Je suis en supposant 32 bits de Windows XP.
Essayez d'éviter d'avoir besoin d'100 MO de mémoire contiguë, si vous êtes malchanceux, un peu aléatoire dll charge eux-mêmes à inconventient points par le biais de votre espace d'adressage disponible rapidement couper de très grandes zones de mémoire contiguë. En fonction de ce que les Api dont vous avez besoin, cela peut être assez difficile à éviter. Il peut être assez surprenant de constater que seulement l'allocation d'un couple de 400 blocs de mémoire en plus d'une partie "normale" de l'utilisation de la mémoire peut vous laisser avec nulle part pour allouer un dernier "petit" 40 MO bloc.
D'autre part, ne préallouer raisonnable de la taille des morceaux à la fois. De l'ordre de 10 mo ou plus est un bon compromis taille de bloc. Si vous pouvez gérer à la partition de vos données dans cette sorte de la taille des morceaux, vous serez en mesure de remplir l'espace d'adressage de façon raisonnablement efficace.
Si vous êtes toujours en cours d'exécution hors de l'espace d'adresse, vous allez avoir besoin pour être en mesure à la page des blocs et sur la base d'une sorte d'algorithme de mise en cache. Choisir la bonne blocs de page dépendra beaucoup de votre traitement algortihm et aura besoin d'une analyse approfondie.
Le choix de l'emplacement à la page des choses est une autre décision. Vous pouvez décider de les inscrire dans les fichiers temporaires. Vous pouvez également étudier de Microsoft à l'Adresse de Fenêtrage Extenstions API. Dans les deux cas, vous devez être prudent dans la conception de votre application pour nettoyer toutes les pointeurs qui pointent vers quelque chose qui est sur le point d'être paginées sinon vraiment mauvaises choses(tm) qui va se passer.
Bonne Chance!
Si vous allez être en effectuant des opérations sur une grande image de la matrice, vous pourriez envisager une technique dite de "mosaïque". L'idée est généralement à la charge de l'image dans la mémoire de sorte que le même bloc contigu d'octets contiennent pas de pixels dans une ligne, mais plutôt d'un carré dans l'espace 2D. Le raisonnement derrière cela est que vous pouvez faire plus d'opérations qui sont plus proches les uns des autres en 2D plutôt que sur une ligne de balayage.
Cela ne va pas réduire votre utilisation de la mémoire, mais peut avoir un impact énorme sur la page de l'échange et de la performance.
Sans beaucoup plus d'informations sur le problème (par exemple la langue), une chose que vous pouvez faire est d'éviter l'attribution de désabonnement en réutilisant des allocations et de ne pas allouer, d'exploitation et de gratuit. Allocateur comme dlmalloc poignées de fragmentation mieux que Win32 tas.
Ce que vous serez frappé ici est la plage d'adresse virtuelle limite, qui, avec 32b Windows vous donne pas plus de 2 GO. Vous devriez aussi être conscient que l'utilisation d'une API graphiques comme DirectX ou OpenGL va utiliser de vastes portions de ces 2 GO de mémoire tampon de trame, de textures et de données similaires.
De 1,5-2 GO pour un 32b application est très difficile à atteindre. La façon la plus élégante de le faire est d'utiliser 64b OS et 64b application. Même avec un OS 64b et 32b de l'application, cela peut être un peu viables, aussi longtemps que vous utilisez
LARGE_ADDRESS_AWARE
.Cependant, comme vous avez besoin de stocker des données d'image, vous pouvez également être en mesure de contourner ce problème en utilisant De Mappage de fichier en tant que banque de mémoire - ce qui peut être fait de manière à ce que vous avez une mémoire commis et accessible, mais de ne pas utiliser toutes les adresses virtuelles.
Deviner ici, que vous avez voulu dire éviter la fragmentation et pas éviter de défragmentation. Aussi deviner que vous travaillez avec un non géré (langage c ou C++ sans doute). Je vous suggère d'allouer de gros morceaux de la mémoire, puis servir les allocations de segment de mémoire de la mémoire allouée blocs. Ce pool de mémoire, car contient de grands blocs de mémoire est lessely sujettes à la fragmentation. Pour résumer, vous devez mettre en œuvre une coutume allocateur de mémoire.
Voir quelques idées générales sur ce ici.
Je gues, vous êtes à l'aide de quelque chose de non géré, parce que dans la gestion des plates-formes du système (garbage collector) prend soin de la fragmentation.
Pour le C/C++, vous pouvez utiliser un autre programme d'allocation de celui par défaut. (il y avait alrady quelques discussions à propos de allocateurs sur stackowerflow).
Aussi, vous pouvez créer votre propre stockage de données. Par exemple, dans le projet sur lequel je travaille actuellement, nous avons une coutume de stockage (piscine) pour les bitmaps (nous les stocker dans une large états contigus morceau de mémoire), parce que nous avons beaucoup d'entre eux, et nous gardons la trace des tas de fragmentation et de le défragmenter lors de la fragmentation est grosse.
Vous pourriez avoir besoin pour mettre en œuvre le manuel de gestion de la mémoire. Est les données d'image à long terme? Si pas, alors vous pouvez utiliser le modèle utilisé par le serveur web apache: allocation de grandes quantités de mémoire et de les encapsuler dans des pools de mémoire. Transmettre ces piscines comme le dernier argument dans les fonctions, de sorte qu'ils peuvent utiliser la piscine pour satisfaire le besoin d'allouer de la mémoire temporaire. Une fois la chaîne d'appel est terminé, toute la mémoire dans la piscine devrait être plus utilisé, de sorte que vous pouvez faire défiler la zone de mémoire et utilisé à nouveau. Les Allocations sont rapides, car ils ne signifier l'ajout d'une valeur à un pointeur. Libération de la mémoire est très rapide, puisque vous ne serez libres de très gros blocs de mémoire à la fois.
Si votre demande est multithread, vous pourriez avoir besoin de stocker de la piscine dans un thread local storage, pour éviter de fausser le filetage de la communication frais généraux.
Si vous pouvez isoler précisément les endroits où vous êtes susceptibles d'allouer des blocs volumineux, vous pouvez (sur Windows) directement appel VirtualAlloc au lieu de passer par le gestionnaire de mémoire. Cela permettra d'éviter la fragmentation dans le gestionnaire de mémoire.
C'est une solution facile et il ne vous oblige pas à utiliser un gestionnaire de mémoire.