2017-07-19 83 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确保复制的内存效率更低。 –