2015-11-26 9 views
5

Übersicht: Nach einigen Tagen der Recherche konnte ich keine schnelle, effiziente Möglichkeit finden, einen Vektor in eine Datei zu schreiben/zu lesen. Die Mehrheit der Antworten, die ich gesehen habe, involviert jedes einzelne Element in die Datei hinein/heraus. Dies ist unglaublich zeitaufwändig, da die Anzahl der Elemente zunimmt. Darüber hinaus konnte ich keinen Versuch auf eine Antwort zu meinem spezifischen Problem finden. Also, bitte, stellen Sie sicher, dass Ihre Lösung für meine spezifischen Umstand funktioniert (d. H. Lesen Sie die gesamte Frage).Effiziente Möglichkeit zum Lesen/Schreiben von Vektoren in Datei

Mein Problem: Ich habe eine sehr große Datenstruktur, die Pixelinformationen über Bilder enthält. Es gibt 60.000 Bilder mit jeweils 784 Pixeln. Jedes Bild ist ein Bild einer handschriftlichen Ziffer. Also muss ich zusätzlich zu den 60.000 * 784 Pixeln ein Label hinzufügen, damit ich weiß, welche Ziffer das Bild darstellt. Das Etikett, das ich benutze, was notwendig ist, wenn man es im Rahmen des gesamten Projekts betrachtet, ist ein Vektor mit 10 Möglichkeiten, die eine 0, 1, 2 ... 9 darstellen, von denen nur eine eine '1'/'enthält. wahr 'während der Rest' 0 '/' falsch 'ist. Darüber hinaus erfordert diese Datenstruktur aufgrund der Erfordernisse der linearen Algebra während des gesamten Rests des Projekts, dass die Information in einer "Col" -Struktur gespeichert wird, die in der Armadillo Linear Algebra Library verwendet wird. Also wird die Struktur, die ich in einer Datei speichern/einlesen möchte, als std::vector<std::vector<arma::Col<double>>> deklariert.

Hier ist die Funktion, die ich jetzt die Daten speichern verwenden, Kontext zu geben:

void SaveTrainingData(vector<vector<Col<double>>> trainingData) //format: trainingData[60000][2][784, 10] 
{ 
    ofstream ofile("VectorizedTrainingData.dat", ios::binary); 

    for (int i = 0; i < trainingData.size(); i++) 
     for (int j = 0; j < trainingData[i].size(); j++) 
      for (int k = 0; k < trainingData[i][j].size(); k++) 
       ofile.write((char *)&trainingData[i][j][k], sizeof(double)); 
} 

Wenn Sie Fragen haben, zögern Sie bitte nicht fragen! Danke im Voraus.

+0

'void SaveTrainingData (Vektor >> Trainingsdaten)' Wenn Sie den Vektor nicht nach Wert übergeben, könnten die Dinge nur beim Funktionsaufruf beschleunigt werden. Führen Sie diese Option auch mit aktivierten Optimierungen oder einer "nicht optimierten" Debug-Version Ihres Programms aus? Beachten Sie außerdem, dass die Festplatten-E/A in einigen Punkten schwer zu optimieren ist, da ein großer Teil davon auf die Leistung der Festplatte zurückzuführen ist. – PaulMcKenzie

Antwort

0

Ich hatte Dokumentation zu diesem Armadillo Bibliothek zu sehen, aber es scheint, wie Col ist eine zusammenhängende, dichte Vektorklasse. Wir können auf die zusammenhängende Darstellung abhängen eine verschachtelte Schleife zu eliminieren, etwa so:

// format: trainingData[60000][2][784, 10] 
void SaveTrainingData(const vector<vector<Col<double>>>& trainingData) 
{ 
    ofstream ofile("VectorizedTrainingData.dat", ios::binary); 

    const int numImages = trainingData.size(); 
    for (int i = 0; i < numImages; i++) 
    { 
     const vector<Col<double>>& img = trainingData[i]; 
     const int numCols = img.size(); 
     for (int j = 0; j < numCols; j++) 
     { 
      const Col<double>& col = img[j]; 
      ofile.write((char*)&col[0], col.size()*sizeof(double)); 
     } 
    } 
} 

Die reduzierte Frequenz in Anrufe write von einem Element in einer Spalte zu einer ganzen Spalte kann bereits ein wenig helfen.

Es kann sich lohnen, dies zu messen, um sicherzustellen, dass Sie tatsächlich mehr I/O-gebundene statt Speicher gebundene sind. Es ist ein wenig schwierig mit der potentiellen Speicherfragmentierung, die all diese Vektoren von Vektoren von Spalten beinhaltet.

Wenn die Größe des inneren Vektors immer gleich ist (was bei jedem Bild mit 784 Pixeln der Fall zu sein scheint), könnten Sie möglicherweise potenziell bessere Ergebnisse mit einem fortlaufenden erzielen, oder dies:

struct Image 
{ 
    Col pixels[768]; 
}; 
... 
vector<Image> trainingData; 

... oder so ähnlich. . Ich konnte nicht ganz nachvollziehen, wie die lineare Algebra an die Bildreproduktion anknüpft, aber hoffentlich gibt das eine Idee.

+0

Vielen Dank! Das wird mir sehr helfen. Und der lineare Algebra-Kram knüpft später an den Rest des Projekts an, ist also hier nicht wirklich relevant, nur notwendig für den Rest des Programms. – Rob

+0

Haben Sie zusätzliche Informationen, wenn es um das Lesen der Datei geht? – Rob

+0

@Rob Reading sollte ziemlich symmetrisch mit dem Schreiben sein - Sie können so ziemlich das gleiche tun. Glauben Sie nicht, dass wir da noch etwas hinzufügen können - ziemlich genau I/O von Binärdaten. –

0

Ich habe Armadillo nicht verwendet, aber seit einem Col ist eine 1 × N-Matrix und das soll linear gespeichert werden, können Sie die k Schleife loszuwerden und schreiben in einem Rutsch die gesamte Spalte aus:

ofile.write((char *)&trainingData[i][j][0], sizeof(double) * trainingData[i][j].size()); 

Wenn das nicht funktioniert, kopieren Sie die Elemente aus dem Col in einen lokalen Vektor und schreiben Sie diese dann in die Datei (da die Dateioperation viel langsamer ist als das Kopieren einiger Doppelpunkte).

Sie wahrscheinlich auch die Größe des Vektors schreiben möchten, bevor alle Elemente zu schreiben, so dass Sie wissen, wie viele es in lesen sind.

+0

Danke! Ich werde es ausprobieren! Außerdem schreibe ich normalerweise die Größe des Vektors in die Datei vor den Elementen, aber dieses Mal, in dem Bemühen, so viele unnötige Daten wie möglich zu eliminieren (da ich die Größen aller Vektoren im Voraus kenne), habe ich sie entfernt . – Rob

Verwandte Themen