【问题标题】:Unexpected behaviour when chunking with multiple netcdf files in xarray/dask使用 xarray/dask 中的多个 netcdf 文件分块时的意外行为
【发布时间】:2020-11-05 23:10:32
【问题描述】:

我正在处理一组 468 个 netcdf 文件,总计 12GB。每个文件只有一个地球物理变量的全局快照,即每个文件的数据形状为(1, 1801, 3600),对应于维度('time', 'latitude', 'longitude')

我的 RAM 是 8GB,所以我需要分块。我正在使用xarray.open_mfdataset 创建一个xarray 数据集,我发现在调用xarray.open_mfdataset 或使用方法.chunk 进行重新分块时使用参数块具有完全不同的结果。类似问题被报告here 没有得到任何回应。

从 xarray 文档来看,调用 xarray.open_dataset 或使用 .chunk 重新分块时的分块应该完全相同...

http://xarray.pydata.org/en/stable/dask.html

...但似乎并非如此。我在这里分享我的例子。

1) 呼叫 xarray.open_mfdataset 时沿空间维度(经度、纬度)进行分块,但时间维度未分块。

import xarray as xr

data1 = xr.open_mfdataset('/data/cds_downloads/2m_temperature/*.nc',
                          concat_dim='time', combine='nested',
                          chunks = {'longitude':400, 'latitude':200}) \
                         .chunk({'time':-1})
data1.t2m.data

with ProgressBar():
    data1.std('time').compute()

[########################################] | 100% Completed |  5min 44.1s

在这种情况下一切正常。

2) 使用方法.chunk 沿空间维度(经度、纬度)进行分块,但未对时间维度进行分块。

data2=xr.open_mfdataset('/data/cds_downloads/2m_temperature/*.nc',
                        concat_dim='time',combine='nested') \
                       .chunk({'time': -1, 'longitude':400, 'latitude':200})
data2.t2m.data

如图所示,显然现在的分块与 1) 中的完全相同。不过……

with ProgressBar():
    data2.std('time').compute()

[#####################################   ] | 93% Completed |  1min 50.8s

...std 的计算无法完成,jupyter notebook 内核由于超出内存限制而没有消息而死,因为我可以使用htop 检查监控...这可能意味着分块确实没有占用放置在现实中,所有没有块的数据集都被加载到内存中。

3) 呼叫xarray.open_mfdataset 时沿空间维度(经度、纬度)进行分块,并默认将时间维度分块(每个文件一个块)。

理论上这种情况应该比 1) 慢得多,因为 std 的计算是沿时间维度完成的,因此不必要地生成了更多的块(现在 421420 个块与 (1) 中的 90 个块)。

data3 = xr.open_mfdataset('/data/cds_downloads/2m_temperature/*.nc',
                          concat_dim='time', combine='nested',
                          chunks = {'longitude':400, 'latitude':200})
data3.t2m.data

with ProgressBar():
    data3.std('time').compute()

[########################################] | 100% Completed |  5min 51.2s

但是没有内存问题,计算所需的时间几乎与情况 1) 相同。这再次表明.chunk 方法似乎无法正常工作。

任何人都知道这是否有意义或如何解决这个问题?我需要能够根据需要执行的特定计算来更改分块。

谢谢

PD:我使用的是 xarray 版本 0.15.1

【问题讨论】:

  • 我已经使用 xr.open_dataset 和一个大型 netcdf 文件(而不是一组数百个较小的 netcdf 文件)进行了测试,并且出现了同样的问题。方法 .chunk 似乎对性能没有明显影响。
  • 我在 open_mfdataset 和之后发现了类似的分块。我认为第一个比较慢,但我无法真正确定它,而且我刚刚开始学习 xarray。我目前的方法是在打开期间不打扰分块(因为还没有真正读取任何内容?)和之后的分块,尤其是在删除时间块时 .chunk({'time':-1}。这似乎对一些原因。然后我使用 .persist() 或 .compute() ,这是真正发生的事情。
  • 那么,@Paul 你的意思是在调用 open_mfdataset 后使用 .chunk 对计算时的性能有明显影响吗?如果是这样的话,我会非常惊讶。我发现的工作解决方案是相反的;只需忘记 .chunk 并创建不同的数据数组对象,调用 open_mfdataset 并将不同的值传递给其中的块参数。在我的情况下,这似乎真的很好。

标签: python dask netcdf python-xarray chunking


【解决方案1】:

我需要能够根据我需要执行的特定计算来更改分块。

是的,计算将对块结构高度敏感。

在计算中尽早分块(最好是在读取数据时)是理想的,因为这样可以简化整体计算。

一般来说,我推荐更大的块大小。见https://docs.dask.org/en/latest/best-practices.html#avoid-very-large-graphs

【讨论】:

    猜你喜欢
    • 2019-06-19
    • 2018-04-23
    • 1970-01-01
    • 2020-10-28
    • 2021-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-29
    相关资源
    最近更新 更多