исключение — большая многомерная векторная инициализация переполнения стека

Я пытаюсь загрузить результаты моделирования из файла в вектор. Код хорошо работает для небольших и средних объемов данных. Когда я пытаюсь загрузить большие файлы, я получаю исключение. Массив, приводящий к сбою моей программы, составляет около 17000 * 7 * 3000 элементов. Я попытался разбить инициализацию на несколько шагов, но она также потерпела крах. Не могли бы вы сказать мне, если я могу сделать что-то, чтобы это работало?

//////////////////////////////////////////////////////////
//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;
}
}
}
}

}

Место, где происходит исключение, tab_wj.push_back...

Когда я попытался разделить инициализацию на более чем один шаг, я написал:

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);

Потом разбился наконец один из этих строк.

Спасибо за любую помощь!

2

Решение

Похоже, он получает исключение при распределении памяти.
станд :: вектор<> должен перераспределить свое хранилище при добавлении в него новых элементов.
Он не делает это для каждого push_back (), потому что выделяет больше, чем нужно.
Вектор<> размера 5 может иметь место для 8 элементов (размер () и емкость ()). Когда вы вставляете 9-й элемент, он должен перераспределиться, и обычно он удваивает свою емкость (с 8 до 16 (*)).

Это перераспределение может фрагментировать вашу кучу.
Для улучшения вы можете предварительно выделить вектор под размер, который ему в конечном итоге понадобится, поэтому ему никогда не потребуется перераспределять. вектор :: резерв ()
Итак, если вы знаете, что в конечном итоге вам понадобится 17000 * 7 * 3000, зарезервируйте это заранее.

Кроме того, если у вас много маленьких векторов, их размещение в небольшом размере может снизить ваши требования к памяти. Обычно вектор<> имеет размер по умолчанию, который может быть 8 или 16. Если вы когда-либо вставляете только 3 элемента, то вы тратите много памяти. При выделении вектора я считаю, что вы можете указать его начальную емкость.

Поскольку вы используете вложенные векторы, каждый из них, в свою очередь, будет иметь свои собственные распределения. В зависимости от вашей версии C ++, вставка вектора в вектор может вызвать несколько распределений.

Вы можете попробовать реструктурировать код, чтобы не требовать вложенных векторов.

(*): наивная векторная реализация удваивает размер выделения, когда ей требуется больше места, но коэффициент 1,6 лучше по ряду причин (он так же эффективен, как и big-O, и приводит к гораздо меньшей фрагментации памяти). Смотрите «Золотое сечение»: https://en.wikipedia.org/wiki/Golden_ratio

1

Другие решения


По вопросам рекламы [email protected]