NetCDF文件 - 为什么修复记录维度后文件大小为1/3?

时间:2015-10-29 10:37:08

标签: python netcdf nco large-data

我正在努力解决这个问题。

我创建了一个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程序,用循环中的数据填充这个文件(因此无限记录维度 - 我不知道apriori文件有多大)。

填充文件后,大小为103MB。

我的问题是从这个文件读取数据非常慢。我猜这是与分块和未命名的point维度有关吗?

我在文件上运行ncks --fix_rec_dmn并且(经过大量搅拌)后,它生成了一个新的netCDF文件,其大小只有32MB(对于它包含的数据大小合适)。

这是一个巨大的差异 - 为什么原始文件如此臃肿?此外 - 访问此文件中的数据的速度要快几个数量级。例如,在Python中,读取hs变量的内容在原始文件上花费2秒,在固定记录维度文件上花费40毫秒。

我遇到的问题是我的一些文件包含很多点并且似乎太大而无法运行ncks(我的机器用尽了备忘录而我有8GB),所以我不能将所有数据转换为固定记录维度。

任何人都可以解释为什么文件大小如此不同以及如何使原始文件更小更高效地阅读?

顺便说一下 - 我没有使用zlib压缩(我选择将浮点值缩放为整数短)。

克里斯

修改 我的Python代码实际上是在3个月内构建了一个单个时间序列文件,其中包含来自多个单独模型预测文件的并置模型和观察数据。我的预测模型每天运行4次,我整合了3个月的数据,因此大约有120个文件。

该程序从每个文件中提取预测期的一个子集(例如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输出看起来很臃肿。

3 个答案:

答案 0 :(得分:1)

我的经验是,记录维度的默认chunksize取决于下面的netCDF库的版本。对于4.3.3.1,它是524288. 275935记录大约是记录块的一半。 ncks会自动选择(不告诉你)比netCDF默认值更合理的块,因此输出会更好地优化。我想这就是正在发生的事情。见http://nco.sf.net/nco.html#cnk

答案 1 :(得分:0)

Please try to provide a code that works without modification if possible, I had to edit to get it working, but it wasn't too difficult.

import netCDF4 as nc
import numpy as np
dout = nc.Dataset('testdset.nc4', mode='w', clobber=True, format="NETCDF4")
dout.createDimension('point', size=None)
dout.createDimension('realization', size=24)
for varname in ['mod_hs','mod_ws']:
    v = dout.createVariable(varname, np.short, 
            dimensions=('point', 'realization'), zlib=False,chunksizes=[1000,24])
    v.scale_factor = 0.01
date = 1
end_date = 5000
n = 0
while date < end_date: 
    sz=100
    dout.variables['mod_hs'][n:n+sz,:] = np.ones((sz,24))
    dout.variables['mod_ws'][n:n+sz,:] = np.ones((sz,24))
    n += sz
    date += 1
dout.close()

The main difference is in createVariable command. For file size, without providing "chunksizes" in creating variable, I also got twice as large file compared to when I added it. So for file size it should do the trick. For reading variables from file, I did not notice any difference actually, maybe I should add more variables? Anyway, it should be clear how to add chunk size now, You probably need to test a bit to get good conf for Your problem. Feel free to ask more if it still does not work for You, and if You want to understand more about chunking, read the hdf5 docs

答案 2 :(得分:0)

我认为您的问题是无限维度的默认块大小为1,这会产生大量内部HDF5结构。通过明确设置chunksize(显然无限制的尺寸),第二个例子在空间和时间方面做得更好。

无限尺寸需要在HDF5 / netCDF4中进行分块,因此如果您想要无限尺寸,则必须考虑分块性能,如您所发现的那样。

更多信息:

https://www.unidata.ucar.edu/software/netcdf/docs/netcdf_perf_chunking.html