2014-08-29 49 views
5

我很困惑的操作看起來像這樣。我一直在普通的Numpy數組上做這個,但是在一個memmap上,我想知道它是如何工作的。在Memmapped陣列上執行操作的正確方法

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數組的內部工作原理!

謝謝...

回答

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

+0

如果可用,您必須使用'out'參數。否則,你總是得到臨時副本。 (當然就地操作符'+ ='通常使用out參數) – seberg 2014-09-04 09:57:14

+0

@seberg你能詳細解釋一下嗎?什麼是'out'論證? – user1265125 2014-09-05 13:15:30