2

シミュレーション結果をファイルからベクトルにロードしようとしています。このコードは、少量および中量のデータに適しています。大きなファイルをロードしようとすると、例外が発生します。プログラムをクラッシュさせる配列は、約 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);

その後、これらの行の最後の 1 つでクラッシュしました。

助けてくれてありがとう!

4

1 に答える 1

1

メモリの割り当て中に例外が発生しているようです。std::vector<> は、新しいアイテムを追加するときにストレージを再割り当てする必要があります。必要以上に割り当てるため、各 push_back() に対してこれを行いません。サイズ 5 の vector<> には、実際には 8 項目分のスペースがある場合があります (size() と capacity())。9 番目のアイテムを挿入すると、再割り当てする必要があり、通常は容量が 2 倍になります (8 から 16 (*))。

この再割り当てにより、ヒープが断片化する可能性があります。改善するために、最終的に必要になるサイズにベクトルを事前に割り当てることができるため、再割り当てする必要はありません。vector::reserve() したがって、最終的に 17000*7*3000 が必要になることがわかっている場合は、これを事前に予約してください。

また、小さいベクトルが多数ある場合は、それらを小さいサイズで割り当てると、必要なメモリ量を減らすことができます。通常、vector<> のデフォルト サイズは 8 または 16 です。3 つのアイテムしか挿入しない場合は、多くのストレージを無駄にしています。ベクトルの割り当て中に、その初期容量を指定できると思います。

ネストされたベクトルを使用しているため、これらのそれぞれに独自の割り当てがあります。C++ のバージョンによっては、ベクターをベクターにプッシュすると、多数の割り当てが発生する可能性があります。

ネストされたベクトルを必要としないように、コードを再構築してみてください。

(*): 単純なベクター実装では、より多くのスペースが必要な場合に割り当てサイズを 2 倍にしますが、1.6 倍の方が多くの理由で優れています (同じように big-O 効率が高く、メモリの断片化がはるかに少なくなります)。「黄金比」を参照してください: https://en.wikipedia.org/wiki/Golden_ratio

于 2015-07-28T21:25:28.017 に答える