调整numpy.memmap数组的大小

Mic*_*ael 22 python arrays resize mmap numpy

我正在使用一堆大型numpy数组,并且由于这些数组最近开始咀嚼太多内存,我想用numpy.memmap实例替换它们.问题是,我现在必须调整阵列的大小,我最好这样做.这对于普通数组非常有效,但是在memmaps上尝试这一点会抱怨,数据可能会被共享,甚至禁用重新检查也无济于事.

a = np.arange(10)
a.resize(20)
a
>>> array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

a = np.memmap('bla.bin', dtype=int)
a
>>> memmap([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])

a.resize(20, refcheck=False)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-41-f1546111a7a1> in <module>()
----> 1 a.resize(20, refcheck=False)

ValueError: cannot resize this array: it does not own its data
Run Code Online (Sandbox Code Playgroud)

调整底层mmap缓冲区的大小非常合适.问题是如何将这些更改反映到数组对象.我已经看到了这种解决方法,但不幸的是它没有调整阵列的大小.还有一些关于调整mmaps大小的numpy文档,但它显然不起作用,至少对于1.8.0版本.任何其他想法,如何覆盖内置的大小调整检查?

www*_*ger 13

问题是创建数组时标志OWNDATA为False.您可以通过在创建数组时要求标志为True来更改它:

>>> a = np.require(np.memmap('bla.bin', dtype=int), requirements=['O'])
>>> a.shape
(10,)
>>> a.flags
  C_CONTIGUOUS : True
  F_CONTIGUOUS : True
  OWNDATA : True
  WRITEABLE : True
  ALIGNED : True
  UPDATEIFCOPY : False
>>> a.resize(20, refcheck=False)
>>> a.shape
(20,)
Run Code Online (Sandbox Code Playgroud)

唯一需要注意的是,它可以创建数组并制作副本以确保满足要求.

编辑以解决保存问题:

如果要将重新调整大小的阵列保存到磁盘,可以将memmap保存为.npy格式的文件,并numpy.memmap在需要重新打开它并用作memmap时打开:

>>> a[9] = 1
>>> np.save('bla.npy',a)
>>> b = np.lib.format.open_memmap('bla.npy', dtype=int, mode='r+')
>>> b
memmap([0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
Run Code Online (Sandbox Code Playgroud)

编辑以提供另一种方法:

您可以通过重新调整基本mmap(a.base或a._mmap,以uint8格式存储)并"重新加载"memmap来接近您正在寻找的内容:

>>> a = np.memmap('bla.bin', dtype=int)
>>> a
memmap([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
>>> a[3] = 7
>>> a
memmap([0, 0, 0, 7, 0, 0, 0, 0, 0, 0])
>>> a.flush()
>>> a = np.memmap('bla.bin', dtype=int)
>>> a
memmap([0, 0, 0, 7, 0, 0, 0, 0, 0, 0])
>>> a.base.resize(20*8)
>>> a.flush()
>>> a = np.memmap('bla.bin', dtype=int)
>>> a
memmap([0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
Run Code Online (Sandbox Code Playgroud)

  • 有趣.不幸的是,对我而言,它总是在内存中创建一个副本.如果我尝试写入数组,刷新,删除和重新打开数组,它将像以前一样再次清空.所以我猜数据从未真正写入磁盘. (2认同)