2016-12-15 2 views
0

Mein Code hat eine 4D-Matrix in es für einige mathematische Problem ist zu lösenC++ 4d Array Speicherfreigabe ist langsam

int**** Sads = new int***[inputImage->HeightLines]; 
for (size_t i = 0; i < inputImage->HeightLines; i++) 
{ 
    Sads[i] = new int**[inputImage->WidthColumns]; 
    for (size_t j = 0; j < inputImage->WidthColumns; j++) 
    { 
     Sads[i][j] = new int*[W_SIZE]; 
     for (size_t k = 0; k < W_SIZE; k++) 
     { 
       Sads[i][j][k] = new int[W_SIZE]; 
     } 
    } 
} 

//do something with Sads... 

for (int i = 0; i < inputImage->HeightLines; i++) 
     { 
      int*** tempI = Sads[i]; 
      for (int j = 0; j < inputImage->WidthColumns; j++) 
      { 
       int** tempJ = tempI[j]; 
       for (int k = 0; k < W_SIZE; k++) 
       { 
        delete[] tempJ[k]; 
       } 
       delete[] Sads[i][j]; 
      } 
      delete[] Sads[i]; 
     } 
     delete[] Sads; 

Die Größen sind sehr groß WidthColumns = 2018 HeightLines = 1332, W_size = 7, die Speicherzuweisung ist sehr schnell, aber die Speicherfreigabe (delete) ist sehr langsam.
Gibt es eine Möglichkeit, es zu optimieren?
Ich müde openMP, aber es wirft nicht zusammenhängende Fehler der fehlenden DLL, die da sind ... Wenn ich die #pragma omp parallel entfernt für alles funktioniert gut. aber langsam ...

+1

Sie sind ein Release-Build ausgeführt wird? Ich habe Fälle gesehen, in denen ein Debug-Build in Visual Studio 100-mal länger ausgeführt hat als ein Release-Build, da die zusätzliche Überprüfung in einem Debug-Build wie dem Test auf Heap-Fehler durchgeführt wird. Betrachte auch ein 1D-Array. – drescherjm

+0

Für die Liebe von all dem, was unheilig im Universum ist, benutze bitte 'std :: vector' und einen passenden Smartpointer. –

+0

@CaptainObvlious Ich tat es ist nicht schneller – Gilad

Antwort

3

Ich würde wahrscheinlich geneigt sein, eine std::vector zu verwenden. Jetzt ist die Speicherzuordnung für mich erledigt (in einer Zuweisung/Freigabe) und ich bekomme eine freie Kopie/Verschiebe-Semantik.

Alles, was ich tun müssen, ist die Offset-Berechnungen liefern:

#include <vector> 
#include <cstddef> 

struct vector4 
{ 
    vector4(std::size_t lines, std::size_t columns) 
      : lines_(lines), columns_(columns) 
    , storage_(totalSize()) 
    {} 

    auto totalSize() const -> std::size_t 
    { 
     return lines_ * columns_ * w_size * w_size; 
    } 

    int* at(std::size_t a) 
    { 
     return storage_.data() + (a * columns_ * w_size * w_size); 
    } 

    int* at(std::size_t a, std::size_t b) 
    { 
     return at(a) + (b * w_size * w_size); 
    } 

    int* at(std::size_t a, std::size_t b, std::size_t c) 
    { 
     return at(a, b) + (c * w_size); 
    } 

    int& at(std::size_t a, std::size_t b, std::size_t c, std::size_t d) 
    { 
     return *(at(a, b, c) + d); 
    } 

private: 

    std::size_t lines_, columns_; 
    static constexpr std::size_t w_size = 32; // ? 
    std::vector<int> storage_; 

}; 

int main() 
{ 
    auto v = vector4(20, 20); 
    v.at(3, 2, 5, 1) = 6; 
    // other things 

    // now let it go out of scope 
} 
+0

Warum 'auto totalSize() const -> std :: size_t' und nicht' std :: size_t totalSize() const'? Gibt es eine Subtilität, die ich vermisse? – YSC

+0

@YSC die beiden Formen sind äquivalent wie von C++ 11 –

+0

Ich weiß, aber warum würden Sie die seltsame Form 'Auto -> Typ 'verwenden, wo Sie die Form verwenden können, die wir alle seit Jahrzehnten gewohnt sind? Jedenfalls sage ich das nicht als Kritik, ich war nur neugierig. – YSC

6

Mit einem Zeiger auf einen Zeiger auf ... ist eine schlechte Idee, weil es Ihre Daten sehr fragmentieren wird.

Ich würde eine Klasse ta erstellen die Indizes zu transformieren und 1D-Array verwenden, ist es ein bisschen komplizierter, aber es wird schneller sein.

Wie auch immer, ein Trick: nichts hindert Sie daran, Ihr int **** mit Zeigern zu einer Zone im Speicher zu erstellen, die nicht spärlich ist (1D-Array, das Sie vorher zugewiesen haben) und dann als 4D-Array zu verwenden.

+2

ihm zeigen, wie es geht –

+0

Richard hat Recht mit seinem Kommentar. Ich weiß, es ist schlecht, ich frage nach besseren Wegen – Gilad

+1

@RichardHodges Das bringt die Frage in die Kategorie "zu breit". –

-2

Down-Wähler, korrigierte ich diesen Code, der zugegebenermaßen vor der Korrektur schrecklich war. Gibt es noch etwas, das eine Abstimmung nach unten verdient? Wenn ja, sag was. Wenn nicht, überdenken Sie bitte Ihre Stimme.


Der richtige Weg, Gebrauch zu erstellen, und löschen Sie einen 4D-Array ist dies, die Schließung der Anweisungsgruppe, die automatischen Variablen löschen verwenden.

{ 
    const int H = 10; 
    const int I = 10; 
    const int J = 10; 
    const int K = 10; 
    int h = 0; 
    int i = 0; 
    int j = 0; 
    int k = 0; 
    int fourDimArray [H][I][J][K]; 
    fourDimArray[h][i][j][k] = 0; 
} 

Wenn Sie eine Notwendigkeit, um dynamisch zuweisen, dann entweder STL Liste oder Vektor-Klasse verwenden, oder vielleicht mit Inline-Methoden etwas wie folgt verwenden den Index des 1D-Arrays aus den 4D-Array-Indizes zu berechnen, wenn Sie prallen müssen Geschwindigkeit.

int * fourDimArrayAsOneDim = new int[H*I*J*K]; 
fourDimArrayAsOneDim[indexFromIndices(h, i, j, k)] = 0; 
delete [] fourDimArrayAsOneDim; 
+1

dies ist nicht legal C++ –

+0

Was ist dieser Code? – Gilad

+0

Korrigiert, um korrekt zu kompilieren und einige Optionen bereitzustellen. Entschuldigung. – FauChristian