5

到目前为止,在我的实验中,我尝试过:

  • xr.open_dataset使用chunksarg,它将数据加载到内存中。
  • 设置一个NetCDF4DataStore, 并调用ds['field'].values,它将数据加载到内存中。
  • 设置一个ScipyDataStorewith mmap='r',并将ds['field'].values数据加载到内存中。

从我所见,设计似乎不是围绕在内存映射数组上实际应用 numpy 函数,而是将小块加载到内存中(有时使用内存映射来这样做)。例如,这条评论这里还有一些相关的评论,关于 not xarray 无法确定一个 numpy 数组是否被映射。

我希望能够将数据表示和切片为xarray.Dataset,并能够调用.values(或.data)来获取ndarray,但让它保持映射(出于共享内存等目的)。

如果分块的 dask 操作至少可以在内存映射数组上操作,直到它真正需要改变某些东西,这也很好,这似乎是可能的,因为 dask 似乎是围绕不可变数组设计的。

不过,我确实发现了一个使用 xarray 的技巧,就是这样做的:

data=np.load('file.npy', mmap_mode='r')
ds=xr.Dataset({'foo': (['dim1', 'dim2'], data)})

在这一点上,类似以下的工作无需将任何内容加载到内存中:

np.sum(ds['foo'].values)
np.sum(ds['foo'][::2,:].values)

...xarray 显然不知道该数组已映射,并且不能np.copy为此类情况强加 a 。

是否有“支持”的方式在 xarray 或 dask 中进行只读内存映射(或就此而言的复制写入)?

4

1 回答 1

3

xr.open_datasetwithchunks=不应该立即将数据加载到内存中,它应该创建一个dask.array懒惰地评估的 。

testfile = '/Users/mdurant/data/smith_sandwell_topo_v8_2.nc'
arr = xr.open_dataset(testfile, chunks={'latitude': 6336//11, 'longitude': 10800//15}).ROSE
arr 

<xarray.DataArray 'ROSE' (latitude: 6336, longitude: 10800)> dask.array</Users/mdurant/data/smith_sandwell_topo_v8_2.nc:/ROSE, shape=(6336, 10800), dtype=float64, chunksize=(576, 720)> Coordinates: * longitude (longitude) float32 0.0166667 0.05 0.0833333 0.116667 0.15 ... * latitude (latitude) float32 -72.0009 -71.9905 -71.9802 -71.9699 ... Attributes: long_name: Topography and Bathymetry ( 8123m -> -10799m) units: meters valid_range: [-32766 32767] unpacked_missing_value: -32767.0 (注意上面的 dask.array)

对此的许多 xarray 操作可能是惰性的,并且按块工作(如果切片,则只会加载所需的块)

arr.sum()

<xarray.DataArray 'ROSE' ()> dask.array<sum-aggregate, shape=(), dtype=float64, chunksize=()>

arr.sum().values    # evaluates

但是,这与内存映射不同,因此如果这不能回答您的问题,我将不胜感激。

使用 dask 的线程调度程序,内存中的值可供其他工作人员使用,因此共享将非常有效。相反,分布式调度器非常擅长识别何时可以在计算图内或图之间重用结果。

于 2017-06-26T14:21:39.400 回答