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

use*_*125 6 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
Run Code Online (Sandbox Code Playgroud)

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

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

1:

arr2 = np.argsort(np.argsort(arr1,axis=0),axis=0) / float(len(arr1)) * 100 
Run Code Online (Sandbox Code Playgroud)

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

考虑到我现在已经创建arr2了一个正确大小的Memmapped数组(用全零填充).

2:

arr2 = np.argsort(np.argsort(arr1,axis=0),axis=0) / float(len(arr1)) * 100
Run Code Online (Sandbox Code Playgroud)

VS

arr2[:] = np.argsort(np.argsort(arr1,axis=0),axis=0) / float(len(arr1)) * 100
Run Code Online (Sandbox Code Playgroud)

有什么不同?

3.

单独计算np.argsort作为临时memmapped数组和np.argsort(np.argsort)临时memmapped数组然后执行操作会更高效吗?由于20GB阵列的argsort数组本身就相当庞大!

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

谢谢...

A.P*_*.P. 2

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

首先,arr = <something>是简单的变量赋值,而arr[:] = <something>赋值给数组的内容。在下面的代码中, after arr[:] = xarrstill 是一个内存映射数组,而 after 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'>
Run Code Online (Sandbox Code Playgroud)

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

>>> 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'>
Run Code Online (Sandbox Code Playgroud)

好吧,现在有什么不同。使用arr[:] = np.argsort(arr),如果我们查看对 memmapping 文件的更改,我们会发现对 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
Run Code Online (Sandbox Code Playgroud)

我们看到它arr仍然保留着它的_mmap属性。

>>> arr._mmap
<mmap.mmap object at 0x7f8e0f086198>
Run Code Online (Sandbox Code Playgroud)

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

>>> 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'>
Run Code Online (Sandbox Code Playgroud)

现在“_mmap”属性为 None。

>>> arr._mmap
>>> type(arr._mmap)
<class 'NoneType'>
Run Code Online (Sandbox Code Playgroud)

现在是第 3 部分。在执行复杂操作时,似乎很容易丢失对内存映射对象的引用。我目前的理解是,你必须将事情分解并用于arr[:] = <>中间结果。

使用 numpy 1.8.1 和 Python 3.4.1