如何在 netcdf 文件中将固定大小的维度转换为无限大小

How to convert fixed size dimension to unlimited in a netcdf file

我每天下载具有以下结构的 600MB netcdf-4 文件:

netcdf 我的文件{
方面:
        time_counter = 18 ;
        深度 = 50 ;
        纬度 = 361 ;
        经度 = 601 ;
变量:
        盐度
        温度等

我正在寻找一种更好的方法将 time_counter 尺寸从固定尺寸 (18) 转换为无限尺寸。

我找到了一种使用 netcdf 命令和 sed 来完成它的方法。像这样:

ncdump myfile.nc | sed -e "s#^.time_counter = 18 ;#time_counter = UNLIMITED ; // (currently 18)#" | ncgen -o myfileunlimited.nc

这对我来说适用于小文件,但是当转储 600 MB 的 netcdf 文件时,会占用大量内存和时间。

有人知道另一种方法吗?

shell 管道只能通过使 sed 步骤仅修改文件的开头并传递其他所有内容来略微改进,但是您拥有的表达式处理起来非常便宜并且不会产生减少花费的时间。

核心问题可能是您花费大量时间 ncdump 将文件信息格式化为文本数据,以及 ncgen 再次将文本数据解析为 NetCDF 文件格式。

由于通过 dump+gen 的路径与显示的一样慢,因此只能使用 NetCDF 功能来转换数据文件。

如果幸运的话,可能有工具可以直接对您的数据文件进行操作以进行更改或转换。如果没有,您可能必须使用 NetCDF 库自己编写它们。

如果您非常不幸,NetCDF-4 文件是带有一些额外元数据的 HDF5 文件。特别是,维度的长度存储在组 _netCDF 中的 _netcdf_dim_info 数据集中(或者 documentation 告诉我)。

可能可以修改那里的信息,将 time_counter 维度的当前长度变成 UNLIMITED 的值(即数字 0),但是如果你这样做,你 真的 需要验证生成文件的完整性,正如文档巧妙地指出的那样:

"Note that modifying these files with HDF5 will almost certainly make them unreadable to netCDF-4."

附带说明一下,如果此过程对您的团队很重要,则可能值得研究哪些硬件可以更快地完成任务。在我的 Bulldozer 系统上,转换一个 78 兆字节文件的过程需要 20 秒,使用大约 500 MB 内存用于 ncgen 工作集(1 GB 虚拟)和 12 MB 内存用于 ncdump 工作集(111 MB 虚拟),每个任务占用更好的核心部分。

任何像样的磁盘都应该在 10 秒左右的时间内 read/sink 您的文件,内存并不重要,只要您不交换,所以 CPU 可能是您最关心的问题dump+gen 路由。

如果并发内存使用是一个大问题,您可以通过将 sed 的中间结果保存到磁盘上来用一些字节换取 space,这可能需要 1.5 GB 左右。

您的回答很有见地。我并不是真的在寻找改进此 ncdump-sed-ncgen 方法的方法,我知道转储 600MB 的 netcdf 文件在文本文件(CDL 表示)中使用的 space 几乎是原来的 5 倍。然后再修改一些header文本,再生成netcdf文件,感觉效率不是很高。

我阅读了最新的 NCO 命令文档,发现了一个特定于 ncks 的选项“--mk_rec_dmn”。 Ncks主要是将数据提取写入或追加到一个新的netcdf文件中,那么这似乎是更好的方法,提取myfile.nc的所有数据并写入一个新的记录维度(无限维度),其中“--mk_rec_dmn”,然后替换旧文件。

ncks --mk_rec_dmn time_counter myfile.nc -o myfileunlimited.nc ; mv myfileunlimited.nc myfile.nc 

做相反的操作(记录维度到固定大小)将是。

ncks --fix_rec_dmn time_counter myfile.nc -o myfilefixedsize.nc ; mv myfilefixedsize.nc myfile.nc

您可以使用 xarray python package's xr.to_netdf() method, then optimise memory usage via using Dask.

您只需将维度的名称传递给 unlimited_dims 参数并使用 chunks 拆分数据即可。例如:

import xarray as xr
ds = xr.open_dataset('myfile.nc', chunks={'time_counter': 18})
ds.to_netcdf('myfileunlimited.nc', unlimited_dims={'time_counter':True})

结合Dask and xarray linked here有一个很好的总结。