Reputation: 41
I am trying to load simulation results from a file into a vector. The code works well for small and medium amount of data. When I try do load big files I get an exception. The array that makes my program crash is about 17000*7*3000 elements. I've tried splitting initialization into few steps but it has crashed as well. Could you please tell me if I can do something to make it work?
//////////////////////////////////////////////////////////
//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;
}
}
}
}
}
The place where an exception occures is tab_wj.push_back...
When I tried to split initialization into more than one step I wrote:
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);
Then it crashed at last one of these lines.
Thanks for any help!
Upvotes: 2
Views: 82
Reputation: 2096
Looks like it is getting an exception while allocating memory. std::vector<> must reallocate its storage as you add new items to it. It doesn't do this for each push_back() because it allocates more than it needs. A vector<> of size 5 might actually have space for 8 items (size() vs. capacity()). When you insert the 9th item it must reallocate, and typically it will double its capacity (from 8 to 16 (*)).
This reallocation can fragment your heap. To improve you can preallocate the vector to the size it will eventually need, so it will never need to reallocate. vector::reserve() So, if you know you will eventually need 17000*7*3000, reserve this up front.
Also, if you have a lot of small vectors, allocating those at a small size can reduce your memory requirements. Usually vector<> has a default size which could be 8 or 16. If you only ever insert 3 items, then you are wasting a lot of storage. During allocation of the vector I believe you can specify its initial capacity.
Since you are using nested vectors, each of these will in turn have their own allocations. Depending on your version of C++, pushing a vector onto a vector can cause a number of allocations.
You might try restructuring the code to not require nested vectors.
(*): a naive vector implementation will double the allocation size when it needs more space, but a factor of 1.6 is better for a number of reasons (its just as big-O efficient and leads to much less memory fragmentation). See "The golden ratio": https://en.wikipedia.org/wiki/Golden_ratio
Upvotes: 1