我正在努力解决这个问题。
我创建了一个具有以下维度和变量的 netcdf4 文件(特别注意无限point
维度):
dimensions:
point = UNLIMITED ; // (275935 currently)
realization = 24 ;
variables:
short mod_hs(realization, point) ;
mod_hs:scale_factor = 0.01 ;
short mod_ws(realization, point) ;
mod_ws:scale_factor = 0.01 ;
short obs_hs(point) ;
obs_hs:scale_factor = 0.01 ;
short obs_ws(point) ;
obs_ws:scale_factor = 0.01 ;
short fchr(point) ;
float obs_lat(point) ;
float obs_lon(point) ;
double obs_datetime(point) ;
}
我有一个 Python 程序,它在循环中用数据填充这个文件(因此无限的记录维度 - 我不知道先验文件有多大)。
填充文件后,大小为 103MB。
我的问题是从这个文件中读取数据非常慢。我猜这与分块和无限point
维度有关?
我ncks --fix_rec_dmn
在该文件上运行,(经过大量搅动)它生成了一个新的 netCDF 文件,该文件的大小仅为 32MB(对于它包含的数据来说,这大约是正确的大小)。
这是大小上的巨大差异 - 为什么原始文件如此臃肿?此外 - 访问此文件中的数据要快几个数量级。例如,在 Python 中,读取hs
变量的内容在原始文件上需要 2 秒,而在固定记录维度文件上需要 40 毫秒。
我遇到的问题是我的一些文件包含很多点并且似乎太大而无法运行ncks
(我的机器内存不足,我有 8GB),所以我无法将所有数据转换为固定记录维度.
谁能解释为什么文件大小如此不同,以及如何使原始文件更小,阅读效率更高?
顺便说一句 - 我没有使用 zlib 压缩(我选择将浮点值缩放为整数 short)。
克里斯
编辑 我的 Python 代码本质上是在 3 个月内从多个单独的模型预测文件中构建一个包含并置模型和观测数据的单个时间序列文件。我的预测模型每天运行 4 次,我汇总了 3 个月的数据,因此大约有 120 个文件。
该程序从每个文件中提取预测周期的子集(et T+24h -> T+48h),因此连接文件并不是一件简单的事情。
这是我的代码在做什么的粗略近似(它实际上读/写了更多变量,但为了清楚起见,我在这里只显示 2):
# Create output file:
dout = nc.Dataset(fn, mode='w', clobber=True, format="NETCDF4")
dout.createDimension('point', size=None)
dout.createDimension('realization', size=24)
for varname in ['mod_hs','mod_ws']:
v = ncd.createVariable(varname, np.short,
dimensions=('point', 'realization'), zlib=False)
v.scale_factor = 0.01
# Cycle over dates
date = <some start start>
end_dat = <some end date>
# Keeo track if record dimension ('point') size:
n = 0
while date < end_date:
din = nc.Dataset("<path to input file>", mode='r')
fchr = din.variables['fchr'][:]
# get mask for specific forecast hour range
m = np.logical_and(fchr >= 24, fchr < 48)
sz = np.count_nonzero(m)
if sz == 0:
continue
dout.variables['mod_hs'][n:n+sz,:] = din.variables['mod_hs'][:][m,:]
dout.variables['mod_ws'][n:n+sz,:] = din.variables['mod_wspd'][:][m,:]
# Increment record dimension count:
n += sz
din.close()
# Goto next file
date += dt.timedelta(hours=6)
dout.close()
有趣的是,如果我将输出文件格式NETCDF3_CLASSIC
而不是NETCDF4
输出大小设置为我期望的大小。NETCDF4 输出似乎臃肿。