IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SL & STL C++ Discussion :

bad_alloc sur gros vecteurs


Sujet :

SL & STL C++

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    127
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 127
    Par défaut bad_alloc sur gros vecteurs
    Bonjour,

    Je code une application de calcul sur graphe qui travaille sur de très gros graphes (+20 millions d'arêtes, + 10 millions de sommets).

    Je code en C++ avec code::block / mingw / gcc 4.3.0 et gdb 6.6.

    Lorsque je lance l'appli, le déroulement du programme est le suivant:

    Au lancement, la lecture et la transformation du graphe fait monter l'occupation mémoire à 1,2 go. Ensuite, certaines structures sont vidées et je n'atteint plus que 392 mo de ram. Ensuite, je dois créer un vecteur gigantesque ( qui prend 795 Mo ). Je fais donc un vector::reserve à l'avance (vu que je connais la taille) pour éviter que lorsque j'ajoute des éléments les éléments du vecteur soit déplacés dans un autre bloc mémoire lorsque le bloc courant est de taille insuffisante. Je rappelle que les éléments d'un vecteur sont contigus en mémoire.

    Lorsque je cherche à allouer 795 mo à mon vecteur avec reserve, l'appli me déclenche une exception std::bad_alloc (pour 300 mo ça passe très bien...). J'imagine que ça vient du fait qu'il n'y a plus d'emplacement mémoire libres contigus sur 795 mo... Je précise que la taille de mon vecteur est de 40 millions et que les objets contenus sont des instances d'une classe qui fait 20 octets. On obtient donc 40.000.000*20(taille d'une instance) = 800 mo.

    Ma question est la suivante: Comment m'affranchir de la structure contigues de 800 mo ? Je pensais découper le vecteur en plusieurs vecteurs plus petits mais c'est assez crade... Avez vous une solution? Existe t'il une structure de donnée du type vector qui ne nécessite pas d'espace mémoire contigu? std::deque prendrait trop de mémoire...

    Je précise que je n'ai pas de fuites mémoires et que l'occupation mémoire de l'appli est exactement ce que j'obtiens théoriquement sur papier.

    Cordialement,

    EDIT: J'ai testé deque à la place de vector mais le code devient 2 fois plus lent au début... puis devient encore beaucoup plus lent...

  2. #2
    Membre éprouvé
    Étudiant
    Inscrit en
    Octobre 2007
    Messages
    189
    Détails du profil
    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Octobre 2007
    Messages : 189
    Par défaut
    En observant le graph' proposé ici, j'opterai pour une std::list.

  3. #3
    Membre émérite

    Profil pro
    Inscrit en
    Septembre 2006
    Messages
    717
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2006
    Messages : 717
    Par défaut
    Normalement std::deque serait la solution à ton problème.

    Malheureusement, je ne sais pas pourquoi, la plupart des implémentations utilisent des taille de bloc minuscules. Celle de Microsoft par exemple (Dinkumware) utilise des blocs de UN SEUL ELEMENT si le type fait plus de 8 octets . La preuve :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    #define _DEQUESIZ	(sizeof (_Ty) <= 1 ? 16 \
    	: sizeof (_Ty) <= 2 ? 8 \
    	: sizeof (_Ty) <= 4 ? 4 \
    	: sizeof (_Ty) <= 8 ? 2 : 1)	/* elements per block (a power of 2) */
    Ce qui donne une énorme pénalité tant en vitesse que en occupation mémoire par rapport à std::vector.

    Une solution serait peut-être d'implémenter ta propre classe deque avec une taille de bloc plus importante. Mais il faut quand même s'attendre à une légère dégradation des performances due à la double indirection inhérente à une telle structure.

  4. #4
    Membre confirmé
    Profil pro
    Inscrit en
    Février 2006
    Messages
    127
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2006
    Messages : 127
    Par défaut
    Du coup avec des blocs aussi petits, on tend quasi asymptotiquement vers l'occupation mémoire et la complexité d'opération de la structure list non?

    Il faudrait que j'implémente ma propre deque ou quelque chose de ce style...

    Charmant ...

  5. #5
    Expert confirmé
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Décembre 2003
    Messages
    3 549
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 3 549
    Par défaut
    Passe en 64 bits, ça devrait résoudre le problème.
    Normalement, avec de la mémoire virtuelle, la contiguïté n'est pas un problème.

  6. #6
    Invité
    Invité(e)
    Par défaut
    En utilisant la STL, je pense que la "bonne" solution à ton problème serait de modifier l'allocateur du gros vecteur qui ne passe pas. Je pense aussi que c'est assez dur à mettre au point.

    A mon avis, le plus simple serait de couper le vecteur en 2 ou 3 morceaux qui passent, et de cacher tout cela dans une classe "emballeuse". Si tous tes acces au vecteur se font via l'opérateur [], il te suffit alors de surcharger le [] de la classe emballeuse, et tout se passera comme si celle ci était un gros vecteur. Si tu utilises des itérateurs, il va aussi te falloir redéfinir leur opérateur d'incrémentation (pour qu'ils passent bien, quand il faut, d'un vecteur au suivant).

    Comme ceci crée une indirection supplémentaire, il est possible que cela ralentisse ton code... Si cela pose problème, le découpage de ton problème en sous problèmes plus petits, au niveau du code, sera la solution. Ce n'est effectivement pas très propre, mais c'est souvent la meilleure solution sur de très gros volumes de données.

    Francois

  7. #7
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    As-tu essayé de faire ton reserve avant la montée à 1Go histoire de le garder sous le coude ?

Discussions similaires

  1. Installation ubuntu sur gros disque
    Par sir_gcc dans le forum Administration système
    Réponses: 5
    Dernier message: 03/06/2006, 14h45
  2. [Struts] Problème pour itérer sur un vecteur
    Par vallica dans le forum Struts 1
    Réponses: 5
    Dernier message: 24/04/2006, 15h45
  3. Partitions sur gros disque
    Par zegota dans le forum Composants
    Réponses: 5
    Dernier message: 07/10/2005, 08h10
  4. Avis sur gros problème BDE en Reseau
    Par tipiweb dans le forum Bases de données
    Réponses: 4
    Dernier message: 29/04/2005, 09h25
  5. Zoom sur des vecteurs ou lignes
    Par mat.M dans le forum Algorithmes et structures de données
    Réponses: 7
    Dernier message: 25/11/2002, 10h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo