2016-07-19 26 views
6

Ich arbeite mit großen Matrizen von Daten (Nrow x Ncol), die zu groß sind, um im Speicher gespeichert zu werden. Stattdessen ist es in meinem Arbeitsgebiet Standard, die Daten in einer Binärdatei zu speichern. Aufgrund der Art der Arbeit muss ich nur auf 1 Spalte der Matrix gleichzeitig zugreifen. Ich muss auch in der Lage sein, eine Spalte zu ändern und dann die aktualisierte Spalte wieder in die Binärdatei zu speichern. Bis jetzt ist es mir gelungen herauszufinden, wie man eine Matrix als Binärdatei speichert und wie man 1 'Spalte' der Matrix aus der Binärdatei in den Speicher liest. Nachdem ich jedoch den Inhalt einer Spalte bearbeitet habe, kann ich nicht herausfinden, wie ich diese Spalte wieder in die Binärdatei speichern kann.Julia: Wie ändere ich eine Spalte einer Matrix, die als Binärdatei gespeichert wurde?

Angenommen, die Datendatei ist eine 32-Bit-Identitätsmatrix, die auf der Festplatte gespeichert wurde.

Nrow = 500 
Ncol = 325 
data = eye(Float32,Nrow,Ncol) 
stream_data = open("data","w") 
write(stream_data,data[:]) 
close(stream_data) 

die gesamte Datei von der Festplatte lesen und dann zurück in die Matrix Umformung ist einfach:

stream_data = open("data","r") 
data_matrix = read(stream_data,Float32,Nrow*Ncol) 
data_matrix = reshape(data_matrix,Nrow,Ncol) 
close(stream_data) 

Wie ich schon sagte, die Daten-Matrizen mit denen ich arbeite sind zu groß, um in dem Speicher zu lesen und infolgedessen wäre der oben geschriebene Code normalerweise nicht ausführbar. Stattdessen muss ich mit 1 Spalte gleichzeitig arbeiten. Das Folgende ist eine Lösung, die 1 Spalte zu lesen (z.B. die 7. Spalte) der Matrix in den Speicher:

icol = 7 
stream_data = open("data","r") 
position_data = 4*Nrow*(icol-1) 
seek(stream_data,position_data) 
data_col = read(stream_data,Float32,Nrow) 
close(stream_data) 

anzumerken, dass der Koeffizient ‚4‘ in der Variable ‚position_data‘ ist, weil ich mit Float32 arbeite. Auch ich verstehe nicht ganz, was der Suchbefehl hier tut, aber es scheint mir die richtige Ausgabe auf den folgenden Tests beruht, geben:

data == data_matrix  # true 
data[:,7] == data_col # true 

Aus Gründen dieses Problems kann sagen, ich habe bestimmt, dass die Säule I (dh der 7. Spalte) geladen mit Nullen ersetzt werden muss:

data_col = zeros(Float32,size(data_col)) 

das Problem ist jetzt, um herauszufinden, wie diese Spalte ohne wieder in die Binärdatei speichern eine der anderen zu beeinflussen Daten. Natürlich beabsichtige ich, 'Schreiben' zu verwenden, um diese Aufgabe auszuführen. Ich bin mir jedoch nicht sicher, wie es weitergehen soll. Ich weiß, dass ich damit beginnen muss, einen Stream zu den Daten zu öffnen; aber ich bin mir nicht sicher, welchen "Modus" ich verwenden soll: "w", "w +", "a" oder "a +"? Hier ist ein gescheiterter Versuch, „w“ mit:

icol = 7 
stream_data = open("data","w") 
position_data = 4*Nrow*(icol-1) 
seek(stream_data,position_data) 
write(stream_data,data_col) 
close(stream_data) 

Die ursprüngliche Binärdatei (vor meinem gescheiterter Versuch, die Binärdatei zu bearbeiten) besetzt 650.000 Bytes auf der Festplatte. Dies steht im Einklang mit der Tatsache, dass die Matrix eine Größe von 500 × 325 hat und die Float32-Zahlen 4 Bytes belegen (d. H. 4 · 500 · 325 = 650000). Nach meinem Versuch, die Binärdatei zu bearbeiten, habe ich jedoch beobachtet, dass die Binärdatei jetzt nur 14000 Bytes Platz einnimmt. Eine schnelle mentale Mathematik zeigt, dass 14000 Bytes 7 Spalten von Daten entsprechen (4 * 500 * 7 = 14000). Eine schnelle Überprüfung bestätigt, dass die Binärdatei alle ursprünglichen Daten durch eine neue Matrix der Größe 500x7 ersetzt hat, deren Elemente nur aus Nullen bestehen.

stream_data = open("data","r") 
data_new_matrix = read(stream_data,Float32,Nrow*7) 
data_new_matrix = reshape(data_new_matrix,Nrow,7) 
sum(abs(data_new_matrix)) # 0.0f0 

Was muss ich tun/ändern, um nur die 7. Spalte in der Binärdatei zu ändern?

+0

sind [diese] (http://docs.julaulang.org/en/release-0.4/stdlib/io-network/#memory-map-i-o) irgendwelche Verwendung hier? – daycaster

+0

Vielleicht ändern Sie 'stream_data = open (" data "," w ")' zu 'stream_data = open (" data "," w + ")' in der Vektoraktualisierung. Beachte das 'w +'. Die entsprechende Dokumentation ist http://docs.julaulang.org/en/release-0.4/stdlib/io-network/#Base.open –

+0

[SharedArrays] (http://docs.julaulang.org/en/release-0.4 /stdlib/parallel/#Base.SharedArray) wird alles tun, was Sie gerade für Sie angegeben haben. Benutze den Konstruktor mit dem Dateinamen –

Antwort

1

Statt

icol = 7 
stream_data = open("data","w") 
position_data = 4*Nrow*(icol-1) 
seek(stream_data,position_data) 
write(stream_data,data_col) 
close(stream_data) 

im OP, schreiben

icol = 7 
stream_data = open("data","r+") 
position_data = 4*Nrow*(icol-1) 
seek(stream_data,position_data) 
write(stream_data,data_col) 
close(stream_data) 

heißt ersetzen "w" mit "r+" und alles funktioniert.

Der Verweis auf open ist http://docs.julialang.org/en/release-0.4/stdlib/io-network/#Base.open und es erklärt die verschiedenen Modi. Vorzugsweise sollte open nicht mit dem ursprünglichen etwas verwirrenden aber definitiv langsameren String-Parameter verwendet werden.

+1

Dies scheint genau das zu tun, was ich wollte. Und um sicherzugehen, dass ich verstehe, was Sie über den string-Parameter sagen, sagen Sie, dass es schneller ist, 'stream_data = open (" data ", true, true, false, false, false) statt' stream_data = zu verwenden open ("data", "r +") 'um die Spalte wieder in die Binärdatei zu schreiben? (und etwas ähnliches zum Lesen der Spalte in den Speicher) – Landon

1

Sie SharedArrays für die Notwendigkeit verwenden, können Sie beschreiben:

data=SharedArray("/some/absolute/path/to/a/file", Float32,(Nrow,Ncols)) 
# do something with data 
data[:,1]=a[:,1].+1 
exit() 

# restart julia 
data=SharedArray("/some/absolute/path/to/a/file", Float32,(Nrow,Ncols)) 
@show data[1,1] 
# prints 1 

nun darauf achten, dass man eigentlich Synchronisation zu handhaben von/zu dieser Datei zu lesen/schreiben (wenn Sie async Arbeitnehmer) und dass Sie die Größe des Arrays nicht ändern sollten (außer Sie wissen, was Sie tun).

+0

Das sieht so aus, als würde es den Trick machen. Wenn Sie die Daten als SharedArray laden, lädt es auch die Daten in den Speicher, oder arbeitet es vollständig von der Festplatte? Wenn es vollständig von der Festplatte funktioniert, bin ich der Meinung, dass es am schnellsten wäre, die aktuelle Spalte in eine neue Variable zu extrahieren, damit ich sie im Speicher bearbeiten kann? – Landon

+0

Ich konnte keine Dokumentation finden, um Ihre Fragen zu beantworten. Auf der anderen Seite, angesichts der Philosophie hinter Julia, versuchen Sie es einfach und Profil/später optimieren entsprechend –