2015-07-28 1 views
2

J'essaye de charger des résultats de simulation d'un fichier dans un vecteur. Le code fonctionne bien pour les petites et moyennes quantités de données. Quand j'essaye de charger de gros fichiers, je reçois une exception. Le tableau qui fait planter mon programme est d'environ 17000 * 7 * 3000 éléments. J'ai essayé de fractionner l'initialisation en quelques étapes, mais il s'est également écrasé. Pourriez-vous s'il vous plaît me dire si je peux faire quelque chose pour le faire fonctionner?Initializaton de grand vecteur multidimensionnel C++

////////////////////////////////////////////////////////// 
//Import of surface receivers file 
    for(int freq=0;freq<7;freq++) 
    { 
     filePath=filePath_old; 

     filePath.Replace(wxT("125 Hz"),wxString::Format(wxT("%i"), freqSTI[freq])+wxT(" Hz")); 
     if(importer.ImportBIN(filePath,mainData)) 
     { 
      if(timeTable.size()==0){ 
       for(int idstep=0;idstep<mainData.nbTimeStep;idstep++) 
       { 
        timeTable.push_back(mainData.timeStep*(idstep+1)*1000); 
       } 
      } 
      for(wxInt32 idrs=0;idrs<mainData.tabRsSize;idrs++) 
      { 
       for(wxInt32 idface=0;idface<mainData.tabRs[idrs].dataRec.quantFaces;idface++) 
       { 
        if(tab_wj.size()<idrs+1){ 
         tab_wj.push_back(std::vector<std::vector<std::vector<wxFloat32> > > (mainData.tabRs[idrs].dataRec.quantFaces,std::vector<std::vector<wxFloat32> >(7,std::vector<wxFloat32>(mainData.nbTimeStep,0.f)))); 
        } 
        //Pour chaque enregistrement de cette face 
        int tmp=mainData.tabRs[idrs].dataFaces[idface].dataFace.nbRecords; 
        for(wxInt32 idenr=0;idenr<mainData.tabRs[idrs].dataFaces[idface].dataFace.nbRecords;idenr++) 
        { 
         t_faceValue* faceval=&mainData.tabRs[idrs].dataFaces[idface].tabTimeStep[idenr]; 
         tab_wj[idrs][idface][freq][faceval->timeStep]=faceval->energy; 
        } 
       } 
      } 
     } 

    } 

L'endroit où une exception occures est tab_wj.push_back...

Quand j'ai essayé de diviser l'initialisation en plus d'une étape, j'ai écrit:

std::vector<wxFloat32> t1(mainData.nbTimeStep,0.f); 
std::vector<std::vector<wxFloat32> > t2(7,t1); 
std::vector<std::vector<std::vector<wxFloat32> > > t3(mainData.tabRs[idrs].dataRec.quantFaces,t2); 

Ensuite, il est écrasé enfin une de ces lignes.

Merci pour toute aide!

+2

17000 * 7 * 3000 * 4 octets (en supposant que float32 a une longueur de 4 octets) = 1 428 000 000. C'est un giga-octet et demi. Peut-être n'avez-vous pas assez de RAM ou d'espace d'échange suffisant. –

+0

J'ai 8 Go de RAM donc ça devrait aller. – wavelet

+0

Même si vos 8 Go ne sont pas tous assignés à votre programme. Je vous suggère d'utiliser valgrind pour trouver la racine de votre problème. – user3630220

Répondre

1

Il semble qu'il y ait une exception lors de l'allocation de la mémoire. std :: vector> Vous devez réaffecter son stockage lorsque vous y ajoutez de nouveaux éléments. Il ne le fait pas pour chaque push_back() car il alloue plus que nécessaire. Un vecteur <> de taille 5 peut réellement contenir de l'espace pour 8 éléments (taille() et capacité()). Lorsque vous insérez le 9ème élément, il doit réallouer, et généralement il doublera sa capacité (de 8 à 16 (*)).

Cette réallocation peut fragmenter votre tas. Pour améliorer, vous pouvez préallouer le vecteur à la taille dont il aura éventuellement besoin, donc il n'aura jamais besoin de réaffecter. vector :: reserve() Donc, si vous savez que vous aurez éventuellement besoin de 17000 * 7 * 3000, réservez ceci avant.

En outre, si vous avez beaucoup de petits vecteurs, en allouant les personnes à une petite taille peut réduire vos besoins en mémoire. Généralement le vecteur <> a une taille par défaut qui pourrait être 8 ou 16. Si vous n'insérez que 3 éléments, vous gaspillez beaucoup de stockage. Au cours de l'allocation du vecteur, je crois que vous pouvez spécifier sa capacité initiale.

Puisque vous utilisez des vecteurs imbriqués, chacun de ceux-ci auront à leur tour leurs propres allocations. Selon votre version de C++, pousser un vecteur sur un vecteur peut provoquer un certain nombre d'allocations.

Vous pouvez essayer de restructurer le code pour ne pas avoir besoin de vecteurs imbriqués. (*): Une implémentation vectorielle naïve doublera la taille d'allocation quand elle a besoin de plus d'espace, mais un facteur de 1,6 est meilleur pour un certain nombre de raisons (c'est tout aussi grand-O efficace et conduit à beaucoup moins de fragmentation de mémoire). Voir "Le nombre d'or": https://en.wikipedia.org/wiki/Golden_ratio

+0

Pourriez-vous s'il vous plaît me dire comment réserver de l'espace pour un vecteur multidimensionnel? – wavelet

+0

Vector ne supporte pas les multi-dimensions en tant que telles. Par exemple, cela créera un vecteur imbriqué de 10 par 20. Veuillez noter la différence entre resize() et reserve(). std :: vecteur > x; x.résize (10); pour (int i = 0; i <10; ++ i) { x [i] .réserve (20); } – joeking

+0

'std :: vector v (X * Y * Z)' où 'X',' Y' et 'Z' sont les dimensions souhaitées. Ensuite, utilisez simplement les mathématiques pour déterminer le décalage approprié. – Chad