【发布时间】:2014-12-22 19:45:24
【问题描述】:
如果 X 的类型是 numpy.array 且 dtype='f4'
那么下面一行的内存行为是什么:
X = array(X, dtype=double, copy=False, order='C', subok=True)
是否为X分配新的内存空间(内存使用*2)?
【问题讨论】:
如果 X 的类型是 numpy.array 且 dtype='f4'
那么下面一行的内存行为是什么:
X = array(X, dtype=double, copy=False, order='C', subok=True)
是否为X分配新的内存空间(内存使用*2)?
【问题讨论】:
NumPy doc 对 array 构造函数的 copy 参数有这样的说法:
如果为 true(默认),则复制对象。否则,仅当 array 返回副本、obj 是嵌套序列或需要副本以满足任何其他要求(dtype、顺序等)时才会生成副本。
您提供了“其他要求”之一的示例,dtype。所以答案是,在这种情况下,copy=False 会被忽略,因为必须制作一个副本 才能将 float32 内容转换为更高的精度。
【讨论】:
X.flags前后来验证。
dtype 是 'f4',它是 'float32' 的同义词。
我喜欢做一些小实验,看看我的系统中“真正”发生了什么。这是一个简单的脚本:
import numpy as np
import numpy.random as rand
@profile
def test_size(N=20e6):
x = np.zeros(N, dtype=np.float32)
x[0] = 200
x[N-1] = 123.555
x[0:N] = rand.rand(N)
x = np.array(x, copy=False, dtype=np.double, order='C', subok=True)
x[0:N] = rand.rand(N)
y = np.zeros(N, dtype=np.float32)
y[0] = 500.0
y[1000] = 123.4
y[0:N] = rand.rand(N)
del(x)
del(y)
if __name__ == '__main__':
test_size()
使用python -m memory_profiler ./testProc.py 进行分析时的输出是:
Line # Mem usage Increment Line Contents
================================================
3 17.699 MiB 0.000 MiB @profile
4 def test_size(N=20e6):
5 17.707 MiB 0.008 MiB x = np.zeros(N, dtype=np.float32)
6 17.711 MiB 0.004 MiB x[0] = 200
7 17.719 MiB 0.008 MiB x[N-1] = 123.555
8 94.031 MiB 76.312 MiB x[0:N] = rand.rand(N)
9 170.332 MiB 76.301 MiB x = np.array(x, copy=False, dtype=np.double, order='C', subok=True)
10 170.340 MiB 0.008 MiB x[0:N] = rand.rand(N)
11 170.344 MiB 0.004 MiB y = np.zeros(N, dtype=np.float32)
12 170.344 MiB 0.000 MiB y[0] = 500.0
13 170.344 MiB 0.000 MiB y[1000] = 123.4
14 246.164 MiB 75.820 MiB y[0:N] = rand.rand(N)
15 93.582 MiB -152.582 MiB del(x)
16 17.285 MiB -76.297 MiB del(y)
正如 Joe 所指出的,内存分析器的结果看起来令人惊讶。分析器在每行之后显示内存分配。内存占用在填充数组的行之后扩大,并在删除它们时缩小。在 shell 中运行 ps 的结果是相似的。
进程删除的内存是否真的返回系统堆栈是另一回事。
【讨论】:
x is 的内存分配给您调用 zeros(对于 20e6 float32 应该是 ~76MB),当您调用 np.array(x, copy=False, dtype=np.double) 时,由于 dtype 的差异( float32 不是 float64)。
rand.rand(N) 在将它们分配给x 之前 创建了一个全新的浮点数组,但您的结果显示第10 行没有内存变化。 (第 8 行和第 10 行完全等同于 temp = np.random.rand(N); x[:] = temp。)