【问题标题】:Do xarray or dask really support memory-mapping?xarray 或 dask 真的支持内存映射吗?
【发布时间】:2017-06-24 05:23:42
【问题描述】:

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

  • xr.open_datasetchunks arg,它将数据加载到内存中。
  • 设置NetCDF4DataStore,调用ds['field'].values,它将数据加载到内存中。
  • 使用mmap='r' 设置ScipyDataStore,然后ds['field'].values 将数据加载到内存中。

据我所见,设计似乎不是围绕在内存映射数组上实际应用 numpy 函数,而是将小块加载到内存中(有时使用内存映射来这样做)。例如,this comment。还有一些相关的评论 here 关于 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

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

【问题讨论】:

    标签: numpy dask numpy-memmap xarray


    【解决方案1】:

    xr.open_datasetchunks= 不应该立即将数据加载到内存中,它应该创建一个 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 的线程调度程序,内存中的值可供其他工作人员使用,因此共享将非常有效。相反,分布式调度器非常擅长识别何时可以在计算图内或图之间重用结果。

    【讨论】:

    • 我想如果 xarray/dask 支持内存映射会很酷。但另一方面,块的延迟加载在功能上几乎是等效的。我假设 xarray 默认使用 dask.threaded 调度程序。我正在围绕 xarray/CF 样式的数据模型(用于 Web 可视化应用程序通过 websocket 访问和查询)构建服务器,并试图决定是否依赖我上面描述的 memmapping hack 以及我自己的并行化,而不是黄昏时全力以赴。
    • 数据本身是只读的,但对于某些查询,根据某些参数/过滤器计算动态掩码数组可能很有用。这就是可变的 sharedmem 数组可能派上用场的地方。尽管使用 dask 来计算每个请求的掩码也可能很好。我还有更多的调查要做。顺便说一句,我可能会接受您的回答,因为我的问题似乎是在询问 xarray 的不受支持/未记录的方面,这是一项艰巨的任务。
    • 是的,dask 默认使用线程调度程序,因此 xarray 也是如此,除非您创建了分布式客户端。对于 HDF 文件,这是可取的,因为否则可能存在进程间文件锁定问题。对于通过 xarray/dask 对大型数据集进行交互式可视化,您可能希望查看datashader examples
    • 我担心像((arr&gt;0.75)*arr).sum() 这样的任务图会占用大量内存,因为(arr&gt;0.75) 中间计算是整个数组的大小。但现在对我来说很明显,足迹将只是块大小*Nthreads。我认为这对我的应用程序很有用,不需要内存映射。我正在使用da.einsum 等函数进行服务器端统计查询,而可视化组件目前非常简单。 Datashader 看起来很棒,感谢 HDF 锁定提示。
    猜你喜欢
    • 1970-01-01
    • 2012-09-26
    • 1970-01-01
    • 2015-09-15
    • 2015-06-27
    • 1970-01-01
    • 2016-06-22
    • 2019-03-01
    • 2017-04-16
    相关资源
    最近更新 更多