У меня есть несколько больших файлов netCDF, которые содержат 6 ежечасных данных для земли с разрешением 0,5 градуса.
Существует 360 точек широты, 720 точек долготы и 1420 временных точек в год. У меня есть как годовые файлы (12 ГБ ea), так и один файл с 110-летними данными (1,3 ТБ), хранящийся как netCDF-4 (вот пример данных 1901, 1901.nc, использовать политику, а исходные, общедоступные файлы, с которых я начал с).
Из того, что я понял, должно быть быстрее читать из одного файла netCDF, а не зацикливаться на наборе файлов разделенных по году и первоначально предоставленной переменной.
Я хочу извлечь временные ряды для каждой точки сетки, например. 10 или 30 лет с определенной широты и долготы. Однако я нахожу это очень медленным. В качестве примера мне понадобится 0,01 секунды для чтения в 10 значениях с течением времени из местоположения точки, хотя я могу читать в глобальном срезе 10000 значений из одной временной точки за 0,002 секунды (порядок измерений - это lat, lon, время):
## a time series of 10 points from one location:
library(ncdf4)
met.nc <- nc_open("1901.nc")
system.time(a <- ncvar_get(met.nc, "lwdown", start = c(100,100,1),
count = c(1,1,10)))
user system elapsed
0.001 0.000 0.090
## close down session
## a global slice of 10k points from one time
library(ncdf4)
system.time(met.nc <- nc_open("1901.nc"))
system.time(a <- ncvar_get(met.nc, "lwdown", start = c(100,100,1),
count = c(100,100,1)))
user system elapsed
0.002 0.000 0.002
Я подозреваю, что эти файлы были написаны для оптимизации чтения пространственных слоев, потому что: a) порядок переменных - lat, lon, time, b), который будет логическим порядком для климатических моделей, которые генерировали эти файлы, и c) потому что глобальные экстенты являются наиболее распространенной визуализацией.
Я попытался переупорядочить переменные, чтобы время было первым:
ncpdq -a time,lon,lat 1901.nc 1901_time.nc
(ncpdq из программное обеспечение NCO (netCDF))
> library(ncdf4)
## first with the original data set:
> system.time(met.nc <- nc_open("test/1901.nc"))
user system elapsed
0.024 0.045 22.334
> system.time(a <- ncvar_get(met.nc, "lwdown", start = c(100,100,1), count = c(1, 1, 1000))
+ )
user system elapsed
0.005 0.027 14.958
## now with the rearranged dimensions:
> system.time(met_time.nc <- nc_open("test/1901_time.nc"))
user system elapsed
0.025 0.041 16.704
> system.time(a <- ncvar_get(met_time.nc, "lwdown", start = c(100,100,1), count = c(1, 1, 1000)))
user system elapsed
0.001 0.019 9.660
Как я могу оптимизировать временные ряды чтения в точке, а не слоях больших площадей за один раз? Например, было бы быстрее, если бы файлы были написаны по-разному, например, время, lat, lon? Есть ли "простой" способ преобразования порядка размеров в файле netCDF-4?
Update
(тесты, запрошенные @mdsumner)
library(rbenchmark)
library(ncdf4)
nc <- nc_open("1901.nc")
benchmark(timeseries = ncvar_get(nc, "lwdown",
start = c(1, 1, 50),
count = c(10, 10, 100)),
spacechunk = ncvar_get(nc, "lwdown",
start = c(1, 1, 50),
count = c(100, 100, 1)),
replications = 1000)
test replications elapsed relative user.self sys.self user.child
2 spacechunk 1000 0.909 1.000 0.843 0.066 0
1 timeseries 1000 2.211 2.432 1.103 1.105 0
sys.child
2 0
1 0
Обновление 2:
Я начал разрабатывать решение здесь. Биты и фрагменты находятся в наборе сценариев в github.com/ebimodeling/model-drivers/tree/master/met/cruncep
Сценарии по-прежнему нуждаются в некоторой работе и организации - не все сценарии полезны. Но чтение молниеносно. Не совсем сопоставимо с приведенными выше результатами, но в конце дня я могу мгновенно прочитать шестичасовую временную серию из 1,3-мегабайтного файла (разрешение 0,5 градуса в 2,5 секунды):
system.time(ts <- ncvar_get(met.nc, "lwdown", start = c(50, 1, 1), count = c(160000, 1, 1)))
user system elapsed
0.004 0.000 0.004
(примечание: порядок измерений изменился, как описано здесь: Как указать порядок размеров при использовании ncdf4:: ncvar_get?)