在Memmapped数组上执行操作的正确方法

时间:2014-08-29 11:41:22

标签: python numpy

我对此操作感到困惑。我一直在常规的Numpy阵列上这样做,但是在一个memmap中我想知道它是如何工作的。

arr2 = np.argsort(np.argsort(arr1,axis=0),axis=0) / float(len(arr1)) * 100
#This is basically to calculate Percentile rank of each value wrt the entire column

这是我在普通numpy数组上使用的。

现在。考虑到arr1 现在是一个20GB的memmapped数组,我有几个问题:

1:

arr2 = np.argsort(np.argsort(arr1,axis=0),axis=0) / float(len(arr1)) * 100 

arr2将是一个常规的numpy数组,我假设?所以执行这个会是灾难性的记忆吗?

考虑到我现在创建了arr2作为正确大小的Memmapped数组(填充全零)。

2

arr2 = np.argsort(np.argsort(arr1,axis=0),axis=0) / float(len(arr1)) * 100

VS

arr2[:] = np.argsort(np.argsort(arr1,axis=0),axis=0) / float(len(arr1)) * 100

有什么区别?

第3

单独计算np.argsort作为临时memmapped数组并将np.argsort(np.argsort)作为临时memmapped数组然后执行操作会更节省内存吗?由于20GB阵列的argsort数组本身就非常庞大!

我认为这些问题可以帮助我澄清python中memmapped数组的内部工作原理!

...谢谢

1 个答案:

答案 0 :(得分:2)

我将尝试先回答第2部分,然后回答1和3。

首先,arr = <something>是简单的变量赋值,而arr[:] = <something>分配给数组的内容。在下面的代码中,在arr[:] = x之后,arr仍然是一个memmapped数组,而在arr = x之后,arr是一个ndarray。

>>> arr = np.memmap('mm', dtype='float32', mode='w+', shape=(1,10000000))
>>> type(arr)
<class 'numpy.core.memmap.memmap'>
>>> x = np.ones((1,10000000))
>>> type(x)
<class 'numpy.ndarray'>
>>> arr[:] = x
>>> type(arr)
<class 'numpy.core.memmap.memmap'>
>>> arr = x
>>> type(arr)
<class 'numpy.ndarray'>

np.argsort的情况下,它返回一个与其参数类型相同的数组。 因此,在这种特定情况下,我认为执行arr = np.argsort(x)arr[:] = np.argsort(x)之间应该没有区别。在您的代码中,arr2将是一个memmapped数组。但是有区别。

>>> arr = np.memmap('mm', dtype='float32', mode='w+', shape=(1,10000000))
>>> x = np.ones((1,10000000))
>>> arr[:] = x
>>> type(np.argsort(x))
<class 'numpy.ndarray'>
>>> type(np.argsort(arr))
<class 'numpy.core.memmap.memmap'>

好的,现在有什么不同了。使用arr[:] = np.argsort(arr),如果我们查看memmapped文件的更改,我们会看到对arr的每次更改都会跟随文件md5sum的更改。

>>> import os
>>> import numpy as np
>>> arr = np.memmap('mm', dtype='float32', mode='w+', shape=(1,10000000))
>>> arr[:] = np.zeros((1,10000000))
>>> os.system("md5sum mm")
48e9a108a3ec623652e7988af2f88867  mm
0
>>> arr += 1.1
>>> os.system("md5sum mm")
b8efebf72a02f9c0b93c0bbcafaf8cb1  mm
0
>>> arr[:] = np.argsort(arr)
>>> os.system("md5sum mm")
c3607e7de30240f3e0385b59491ac2ce  mm
0
>>> arr += 1.3
>>> os.system("md5sum mm")
1e6af2af114c70790224abe0e0e5f3f0  mm
0

我们发现arr仍保留其_mmap属性。

>>> arr._mmap
<mmap.mmap object at 0x7f8e0f086198>

现在使用arr = np.argsort(x),我们看到md5sums停止变化。尽管arr的类型是memmapped数组,但它是一个新对象,似乎内存映射被删除。

>>> import os
>>> import numpy as np
>>> arr = np.memmap('mm', dtype='float32', mode='w+', shape=(1,10000000))
>>> arr[:] = np.zeros((1,10000000))
>>> os.system("md5sum mm")
48e9a108a3ec623652e7988af2f88867  mm
0
>>> arr += 1.1
>>> os.system("md5sum mm")
b8efebf72a02f9c0b93c0bbcafaf8cb1  mm
0
>>> arr = np.argsort(arr)
>>> os.system("md5sum mm")
b8efebf72a02f9c0b93c0bbcafaf8cb1  mm
0
>>> arr += 1.3
>>> os.system("md5sum mm")
b8efebf72a02f9c0b93c0bbcafaf8cb1  mm
0
>>> type(arr)
<class 'numpy.core.memmap.memmap'>

现在'_mmap'属性为None。

>>> arr._mmap
>>> type(arr._mmap)
<class 'NoneType'>

现在是第3部分。在执行复杂操作时,似乎很容易丢失对memmapped对象的引用。我目前的理解是你必须分解并使用arr[:] = <>来获得中间结果。

使用numpy 1.8.1和Python 3.4.1