在 python 中处理非常大的 netCDF 文件
Posted
技术标签:
【中文标题】在 python 中处理非常大的 netCDF 文件【英文标题】:Handling very large netCDF files in python 【发布时间】:2012-08-17 13:36:15 【问题描述】:我正在尝试处理来自非常大的 netCDF 文件(每个约 400 Gb)的数据。每个文件都有一些变量,都比系统内存大得多(例如 180 Gb 与 32 Gb RAM)。我正在尝试使用 numpy 和 netCDF4-python 通过一次复制一个切片并对该切片进行操作来对这些变量进行一些操作。不幸的是,读取每个切片需要很长时间,这会影响性能。
例如,其中一个变量是形状为(500, 500, 450, 300)
的数组。我想对切片[:,:,0]
进行操作,所以我做了以下操作:
import netCDF4 as nc
f = nc.Dataset('myfile.ncdf','r+')
myvar = f.variables['myvar']
myslice = myvar[:,:,0]
但最后一步需要很长时间(在我的系统上大约 5 分钟)。例如,如果我在 netcdf 文件中保存了一个形状为 (500, 500, 300)
的变量,那么相同大小的读取操作只需几秒钟。
有什么办法可以加快速度吗?一个明显的路径是转置数组,以便我选择的索引首先出现。但在如此大的文件中,这在内存中是不可能的,而且考虑到一个简单的操作已经花费了很长时间,尝试它似乎更慢。我想要的是一种以 Fortran 接口 get_vara 函数的方式读取 netcdf 文件片段的快速方法。或某种有效转置数组的方法。
【问题讨论】:
如果你想对数据做更多的事情而不仅仅是转置它,看看xarray
模块:它为dask
内存不足数组提供了一个非常好的接口。
【参考方案1】:
您可以使用 nccopy 实用程序转置太大而无法放入内存的 netCDF 变量,此处记录了该实用程序:
http://www.unidata.ucar.edu/netcdf/docs/guide_nccopy.html
这个想法是通过指定块的形状(多维图块)来“重新分块”文件 你想要的变量。您可以指定要用作缓冲区的内存量以及要用作缓冲区的内存量。 用于块缓存,但不清楚如何在这些用途之间最佳地使用内存,所以你 可能只需要尝试一些示例并为它们计时。而不是完全转置一个变量, 您可能希望通过指定具有大量数据的块来“部分转置”它 切片的 2 个大尺寸,而其他尺寸只有几个值。
【讨论】:
感谢拉斯的回答。这很有趣,因为我从来没有过多地研究分块。假设我有一个尺寸为(500、500、300、400)的变量。如果我在第三维上进行 1 的分块,这是否类似于在该轴是最快轴(即连续)的情况下进行部分转置?我确实更改了要阅读更多内容的轴上的分块,但是要获得 3D 切片仍然需要很长时间。我会调查这是否是文件系统/网络问题。 不,将第 3 维中的块长度设为 1 会使该维最慢,因为在沿该维读取时,您将访问每个 4 字节值的 400 MB 块。但是,如果您在每个维度上使用 10 个块(每个块 50x40x30x40),每个块将包含大约 12 MB(假设每个值 4 个字节),并且只需要 10 次读取即可访问沿任何维度的值“圆柱体”(a 50x50x30x40 块)。有关这如何改善某些方向的访问时间的示例,请参阅 2 张幻灯片:unidata.ucar.edu/netcdf/workshops/2011/chunk_cache/Problem.html 对上述评论的更正:将“(a 50x50x30x40 chunk)”替换为“(10 50x50x30x40 chunks)” ... 我有点困惑。假设 (500, 500, 300, 400) 可变大小,我希望快速访问像 (:, :, 0, 0) 这样的切片。我认为在最后两个维度中用 1 分块是最好的(除了转置整个东西)。这种访问的最佳分块是什么?在您的链接中,它说使用第一个维度的较大值和最后一个维度的较小值重新分块会加快对最后一个维度的访问,但您似乎说的相反。【参考方案2】:这是评论,不是答案,但我无法评论以上内容,抱歉。
我了解到您想处理myvar[:,:,i]
,在range(450)
中使用i
。在这种情况下,您将执行以下操作:
for i in range(450):
myslice = myvar[:,:,i]
do_something(slice)
瓶颈在于访问myslice = myvar[:,:,i]
。您是否尝试过比较访问moreslices = myvar[:,:,0:n]
需要多长时间?这将是连续数据,也许您可以节省时间。你会选择n
与你的内存一样大,然后处理下一个数据块moreslices = myvar[:,:,n:2n]
等等。
【讨论】:
感谢您的回答。我比较了访问myvar[:,:,0:n]
的时间,确实与myvar[:,:,0]
的时间差不多。所以这至少是一种方法,但我仍在试图找出为什么会有这样的惩罚开始。请注意,myvar[:,:,0:n]
不是连续的。
嗯,myvar[1,0,0]
确实与myvar[2,0,0]
不连续。但这需要大约相同的时间,因为myvar[i,i,0]
实际上与myvar[i,i,1]
是连续的。现在更有意义了吗?以上是关于在 python 中处理非常大的 netCDF 文件的主要内容,如果未能解决你的问题,请参考以下文章
Python:使用 netCDF4 替换 netcdf 文件中的值