我有一些大型 netCDF 文件,其中包含 0.5 度分辨率的地球 6 小时数据。
每年有360个纬度点、720个经度点和1420个时间点。我有两个年度文件(12 GB ea)和一个包含 110 年数据(1.3 TB)的文件存储为 netCDF-4(这里是 1901 数据的示例,1901.nc,它的使用策略,以及原始的,公共的我开始使用的文件)。
据我了解,从一个 netCDF 文件中读取应该比循环遍历由 year 和最初提供的变量分隔的文件集更快。
我想为每个网格点提取一个时间序列,例如从特定纬度和经度开始的 10 年或 30 年。但是,我发现这非常慢。例如,尽管我可以在 0.002 秒内从单个时间点读取 10000 个值的全局切片(维度的顺序是纬度、经度、时间):
## 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)变量的顺序是纬度、经度、时间,b)这将是生成这些文件的气候模型的逻辑顺序,以及 c)因为全球范围是最常见的可视化。
我试图重新排序变量,以便时间优先:
ncpdq -a time,lon,lat 1901.nc 1901_time.nc
> 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
如何优化某一点的阅读时间序列,而不是一个时间点的大面积层?例如,如果文件以不同的方式编写,例如时间、纬度、经度,会更快吗?有没有一种“简单”的方法来转换 netCDF-4 文件中的维度顺序?
更新
(@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.3TB 文件(2.5 秒内 0.5 度分辨率)中读取 100 年、6 小时的时间序列:
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
(注意:维度的顺序已经改变,如下所述:How can I specify dimension order when using ncdf4::ncvar_get?)