2017-07-19 72 views
0

16Gb機器給出內存不足錯誤。我懷疑轉換是否真的到位。Numpy inplace dtype轉換

import numpy as np 
x = np.ones(int(1.5e9), dtype=np.int64) # 12 Gb 
x.astype(np.float64, copy=False) # gives out of memory error. 

如何進行就地內存轉換?我想轉換數據類型並保存值。例如1.0F變爲整數1

In-place type conversion of a NumPy array

+0

大概可以通過部分來完成。 'y = x.view(dtype = np.float64); y [:10000] = x [:10000] .astype(np.float64)' –

+0

您鏈接的問題不足以解決您的問題?看起來像一個完全重複給我。 – Eric

回答

3

關於copy參數:

默認情況下,astype總是返回一個新分配的數組。如果將此 設置爲false,並且滿足dtypeordersubok 的要求,則會返回輸入數組而不是 的副本。

所以它是有條件的。

In [540]: x=np.arange(10) 
In [542]: x.dtype 
Out[542]: dtype('int32') 
In [543]: z=x.astype('float32',copy=False) 
In [544]: z 
Out[544]: array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.], dtype=float32) 
In [545]: x.__array_interface__ 
Out[545]: 
{'data': (188221848, False), 
'descr': [('', '<i4')], 
'shape': (10,), 
'strides': None, 
'typestr': '<i4', 
'version': 3} 
In [546]: z.__array_interface__ 
Out[546]: 
{'data': (191273640, False), 
'descr': [('', '<f4')], 
'shape': (10,), 
'strides': None, 
'typestr': '<f4', 
'version': 3} 

z具有不同的存儲位置。


在你的鏈接接受的答案似乎工作

In [549]: z=x.view('float32') 
In [550]: z[:]=x 
In [551]: z 
Out[551]: array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.], dtype=float32) 
In [552]: x 
Out[552]: 
array([   0, 1065353216, 1073741824, 1077936128, 1082130432, 
     1084227584, 1086324736, 1088421888, 1090519040, 1091567616]) 
In [553]: z 
Out[553]: array([ 0., 1., 2., 3., 4., 5., 6., 7., 8., 9.], dtype=float32) 
In [555]: x.__array_interface__ 
Out[555]: 
{'data': (188221848, False), 
'descr': [('', '<i4')], 
'shape': (10,), 
'strides': None, 
'typestr': '<i4', 
'version': 3} 
In [556]: z.__array_interface__ 
Out[556]: 
{'data': (188221848, False), 
'descr': [('', '<f4')], 
'shape': (10,), 
'strides': None, 
'typestr': '<f4', 
'version': 3} 

這工作,因爲z共享內存x,但有不同的dtype。當從x複製到z時,它們被轉換爲匹配新的dtype。內存位置被保留。但我不能保證沒有臨時緩衝區。


在情況下,它是不明確的,轉換形式int32float32需要在底層字節的變化。整數的位表示與浮點數的不同。

In [594]: np.array(1, 'int32').tobytes() 
Out[594]: b'\x01\x00\x00\x00' 
In [595]: np.array(1, 'float32').tobytes() 
Out[595]: b'\x00\x00\x80?' 
+0

float32和int32都使用相同數量的內存。但astype仍然使新的副本,這是不必要的和低效的... –

+0

效率與它有什麼關係。每個4字節塊必須經歷相同的轉換過程。無論它被寫回相同或不同的內存位置,在「速度」上都不會有太大的區別。 – hpaulj

+0

我猜測複製比就地執行操作要慢,因爲cpu不必讀/寫額外的緩存行內存。預取應該掩蓋內存延遲。不知道如果沒有複製,預取工作是否更好。 https://stackoverflow.com/questions/3928995/how-do-cache-lines-work確保複製的內存效率更低。 –