2016-07-19 9 views
6

Pracuję z dużymi matrycami danych (Nrow x Ncol), które są zbyt duże, aby można je było przechowywać w pamięci. Zamiast tego standardem w mojej dziedzinie pracy jest zapisywanie danych do pliku binarnego. Ze względu na charakter pracy, potrzebuję tylko dostępu do 1 kolumny macierzy na raz. Muszę też móc modyfikować kolumnę, a następnie zapisać zaktualizowaną kolumnę z powrotem do pliku binarnego. Do tej pory udało mi się dowiedzieć, jak zapisać macierz jako plik binarny i jak odczytać 1 "kolumnę" macierzy z pliku binarnego do pamięci. Jednak po edycji zawartości kolumny nie mogę wymyślić, jak zapisać tę kolumnę z powrotem do pliku binarnego.Julia: Jak zmodyfikować kolumnę matrycy, która została zapisana jako plik binarny?

Jako przykład załóżmy, że plik danych to 32-bitowa macierz tożsamości, która została zapisana na dysku.

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

Czytając cały plik z dysku, a następnie przekształcania z powrotem do macierzy jest prosta:

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

Jak powiedziałem wcześniej, dane macierze Pracuję ze są zbyt duże, aby czytać w pamięci w rezultacie powyższy kod normalnie nie byłby możliwy do wykonania. Zamiast tego muszę pracować z 1 kolumną na raz. Poniżej przedstawiono rozwiązanie odczytu 1 w kolumnie (np 7. kolumn) macierzy do pamięci:

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) 

Należy zauważyć, że współczynnik „4” w zmiennej „position_data”, ponieważ pracuję z Float32. Również nie w pełni zrozumieć, co robi komenda szukać tutaj, ale wydaje się, że daje mi poprawny wynik w oparciu o następujące testy:

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

dla dobra tego problemu, powiedzmy, że mam Ustalono, że kolumna I załadowane (czyli 7 kolumny) musi zostać zastąpione zerami:

data_col = zeros(Float32,size(data_col)) 

problem teraz jest dowiedzieć się, jak zapisać tę kolumnę z powrotem do pliku binarnego bez wpływu na którykolwiek z pozostałych dane. Oczywiście zamierzam użyć "zapisu" do wykonania tego zadania. Jednak nie jestem do końca pewien, jak postępować. Wiem, że muszę zacząć od otwarcia strumienia danych; jednak nie jestem pewien, jakiego "trybu" muszę użyć: "w", "w +", "a" lub "a +"? Tutaj jest nieudana próba z użyciem „w”:

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) 

Oryginalny plik binarny (przed moja nieudana próba edytować plik binarny) zajęte 650000 bajtów na dysku. Jest to zgodne z tym, że macierz ma rozmiar 500x325, a liczby Float32 zajmują 4 bajty (to jest 4 * 500 * 325 = 650000). Jednak po mojej próbie edycji pliku binarnego zauważyłem, że plik binarny zajmuje teraz tylko 14000 bajtów przestrzeni. Jakaś szybka mentalna matematyka pokazuje, że 14000 bajtów odpowiada 7 kolumnom danych (4 * 500 * 7 = 14000). Szybkie sprawdzenie potwierdza, że ​​plik binarny zastąpił wszystkie oryginalne dane nową macierzą o rozmiarze 500x7, której elementy są zerami.

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 

Co muszę zrobić/zmienić, aby modyfikować tylko 7. "kolumnę" w pliku binarnym?

+0

są [te] (http://docs.julialang.org/en/release-0.4/stdlib/io-network/#memory-mapped-i-o) tutaj? – daycaster

+0

Może zmienić 'stream_data = open (" dane "," w ")' na 'stream_data = open (" dane "," w + ")' w aktualizacji wektora. Zwróć uwagę na 'w +'. Odpowiednia dokumentacja to http://docs.julialang.org/en/release-0.4/stdlib/io-network/#Base.open –

+0

[SharedArrays] (http://docs.julialang.org/en/release-0.4 /stdlib/parallel/#Base.SharedArray) zrobi wszystko, co dla ciebie określiłeś. Użyj konstruktora o nazwie pliku –

Odpowiedz

1

Zamiast

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) 

w PO, pisać

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) 

tj zastąpić "w" z "r+" i wszystko działa.

Odwołanie do open to http://docs.julialang.org/en/release-0.4/stdlib/io-network/#Base.open i objaśnia różne tryby. Najlepiej, gdy open nie powinno być używane z pierwotnie nieco mylącym, ale zdecydowanie wolniejszym parametrem ciągowym.

+1

To wydaje się robić dokładnie to, co chciałem. I po prostu upewnij się, że rozumiem, co mówisz o parametrze string, czy mówisz, że będzie szybciej używać 'stream_data = open (" dane ", prawda, prawda, fałsz, fałsz, fałsz)' zamiast 'stream_data = open ("data", "r +") 'do zapisania kolumny z powrotem do pliku binarnego? (i coś podobnego do czytania kolumny w pamięci) – Landon

1

Można użyć SharedArrays na potrzeby opisać:

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 

Teraz pamiętać, że masz za zadanie obsługiwać synchronizację do odczytu/zapisu z/do pliku (jeśli masz pracowników asynchroniczny) i że nie powinieneś zmieniać rozmiaru tablicy (chyba, że ​​wiesz, co robisz).

+0

Wygląda na to, że to wystarczy. Kiedy ładujesz dane jako SharedArray, czy też ładuje dane do pamięci lub działa całkowicie poza dyskiem? Jeśli to działa całkowicie poza dysk, czy mam rację, myślę, że byłoby najszybciej wyodrębnić bieżącą kolumnę do nowej zmiennej, tak, że mogę pracować na nim w pamięci? – Landon

+0

Nie mogę znaleźć żadnej dokumentacji, aby odpowiedzieć na twoje pytania. Z drugiej strony, biorąc pod uwagę filozofię stojącą za Julią, po prostu spróbuj ją i zoptymalizuj odpowiednio później. –

Powiązane problemy