/ / Obsługa bardzo dużych plików netCDF w python - python, numpy, netcdf

Obsługa bardzo dużych plików netCDF w python - python, numpy, netcdf

Próbuję pracować z danymi z bardzo dużychpliki netCDF (~ 400 Gb każdy). Każdy plik ma kilka zmiennych, znacznie większych niż pamięć systemowa (np. 180 Gb vs 32 Gb RAM). Próbuję użyć numpy, a netCDF4-python wykonuje pewne operacje na tych zmiennych, kopiując plasterek i działając na tym plasterku. Niestety, przeczytanie każdego fragmentu, który zabija wydajność, zajmuje naprawdę dużo czasu.

Na przykład jedna ze zmiennych jest tablicą kształtu (500, 500, 450, 300). Chcę operować plasterkiem [:,:,0], więc robię co następuje:

import netCDF4 as nc

f = nc.Dataset("myfile.ncdf","r+")
myvar = f.variables["myvar"]
myslice = myvar[:,:,0]

Ale ostatni krok zajmuje naprawdę dużo czasu (~ 5 min w moim systemie). Jeśli na przykład zapisałem zmienną kształtu (500, 500, 300) w pliku netcdf operacja odczytu tego samego rozmiaru zajmie tylko kilka sekund.

Czy jest jakiś sposób, żeby to przyspieszyć? Oczywistą ścieżką byłoby przetransponowanie tablicy, tak aby indeksy, które wybieram, pojawiły się jako pierwsze. Ale w tak dużym pliku nie byłoby możliwe zrobienie tego w pamięci i wydaje się, że próbowanie tego jest jeszcze wolniejsze, ponieważ prosta operacja zajmuje dużo czasu. Chciałbym szybki sposób na odczyt fragmentu pliku netcdf, w stylu funkcji get_vara interfejsu Fortrana. Lub jakiegoś sposobu wydajnej transpozycji tablicy.

Odpowiedzi:

7 dla odpowiedzi № 1

Za pomocą narzędzia nccopy, które jest tutaj udokumentowane, można transponować zmienne netCDF zbyt duże, aby zmieściły się w pamięci

http://www.unidata.ucar.edu/netcdf/docs/guide_nccopy.html

Pomysł polega na „ponownym” przesłaniu pliku przez określeniejakie kształty kawałków (płytki wielowymiarowe) chcesz dla zmiennych. Możesz określić, ile pamięci ma być używane jako bufor i ile używaj do pamięci podręcznej części, ale nie jest jasne, jak optymalnie wykorzystać pamięć między tymi zastosowaniami, więc Ty być może trzeba będzie po prostu wypróbować kilka przykładów i czas. Zamiast całkowicie transponować zmienną, prawdopodobnie chcesz go „częściowo przetransponować”, określając porcje, które zawierają dużo danych 2 duże wymiary plasterka i tylko kilka wartości wzdłuż innych wymiarów.


3 dla odpowiedzi № 2

To jest komentarz, a nie odpowiedź, ale nie mogę komentować powyższego, przepraszam.

Rozumiem, że chcesz przetwarzać myvar[:,:,i], z i w range(450). W takim przypadku zrobisz coś takiego:

for i in range(450):
myslice = myvar[:,:,i]
do_something(slice)

a wąskim gardłem jest dostęp myslice = myvar[:,:,i]. Czy próbowałeś porównać czas potrzebny na dostęp moreslices = myvar[:,:,0:n]? To byłyby dane contiguos, a może możesz zaoszczędzić na tym czasu. Wybrałbyś n tak duża, jak pozwala na to twoja pamięć, a następnie przetworzyć następny fragment danych moreslices = myvar[:,:,n:2n] i tak dalej.