【问题标题】:Flushing numpy memmap to npy file将 numpy memmap 刷新到 npy 文件
【发布时间】:2016-08-14 15:23:56
【问题描述】:

有没有办法将 numpy memmap 数组保存到 .npy 文件中?显然,有一种方法可以从.npy 文件中加载这样的数组,如下所示

data = numpy.load("input.npy", mmap_mode='r')

但刷新文件并不等同于将其存储为.npy 格式。

如果刷新是唯一的方法,那么有没有办法推断存储数组的形状?我更喜欢在另一个脚本中自动存储和检索(可能再次作为 memmap)的动态形状。

我已经在各个地方搜索过这个,但没有找到任何结果。我现在存储到.npy的方式是

numpy.save(output.filename, output.copy())

这违背了使用 memmap 的想法,但保留了形状。

注意:我知道 hdf5 和 h5py,但我想知道是否有一个纯粹的 numpy 解决方案。

【问题讨论】:

    标签: python numpy mmap memory-mapped-files


    【解决方案1】:

    使用np.save 保存的数组本质上是一个memmap,其标头指定了数据类型、形状和元素顺序。您可以在numpy documentation 中了解更多信息。

    创建np.memmap 时,可以使用offset 参数为该标头保留空间。 numpy 文档指定标头长度应为 64 的倍数:

    假设您为标头保留 2 * 64 = 128 个字节(更多内容见下文):

    import numpy as np
    x = np.memmap('/tmp/x.npy', mode='w+', dtype=np.ubyte, 
                  shape=(int(1E10),), offset=128)
    

    然后,当您完成对 memmap 的操作后,您可以使用 np.lib.format 创建和写入标头:

    header = np.lib.format.header_data_from_array_1_0(x)
    
    with open('/tmp/x.npy', 'r+b') as f:
        np.lib.format.write_array_header_1_0(f, header)
    

    注意,这会从memmap文件的开头写入header,所以如果len(header) > 128,那么它会覆盖部分数据,你的文件将不可读。标头是一个固定长度的魔术字符串(6 个字节)、两个版本字节、两个指定标头长度的字节,以及一个指定“形状”、“描述”和“顺序”的字典的字符串表示形式。如果您知道数组的形状和 dtype (descr),则可以轻松计算标头长度(为简单起见,我将其固定为 128)。

    写完标题后你可以使用np.load加载数据:

    y = np.load('/tmp/x.npy')
    

    如果您保存的 memmap 很大,您可能需要再次将数据加载为 memmap:

    y = np.load('/tmp/x.npy', mmap_mode='r')
    

    【讨论】:

      【解决方案2】:

      有没有办法推断存储数组的形状?

      No。就np.memmap 而言,该文件只是一个缓冲区——它存储数组的内容,但不存储维度、dtype 等。除非它以某种方式包含在数组本身中,否则无法推断该信息。如果您已经创建了一个由简单二进制文件支持的 np.memmap,那么您需要将其内容写入磁盘上的新 .npy 文件。

      您可以通过使用numpy.lib.format.open_memmap 打开新的.npy 文件作为另一个内存映射数组来避免在内存中生成副本:

      import numpy as np
      from numpy.lib.format import open_memmap
      
      # a 10GB memory-mapped array
      x = np.memmap('/tmp/x.mm', mode='w+', dtype=np.ubyte, shape=(int(1E10),))
      
      # create a memory-mapped .npy file with the same dimensions and dtype
      y = open_memmap('/tmp/y.npy', mode='w+', dtype=x.dtype, shape=x.shape)
      
      # copy the array contents
      y[:] = x[:]
      

      【讨论】:

      • 这个open_memmap 函数是一个很棒的发现——我只需要启动一个.npy 支持的数组的方法,但是添加一个选项来保存可能卡在二进制文件中的数组会更好.
      • open_memmap 真的很棒
      猜你喜欢
      • 2018-01-15
      • 1970-01-01
      • 1970-01-01
      • 2019-09-10
      • 2018-07-31
      • 1970-01-01
      • 2016-08-14
      • 2021-12-13
      • 2020-11-30
      相关资源
      最近更新 更多