numpy.array的内存分配,copy = False?

时间:2014-12-22 19:45:24

标签: python memory numpy

如果 X 的类型为 numpy.array dtype ='f4'

然后下面一行的内存行为是什么:

X = array(X, dtype=double, copy=False, order='C', subok=True)

是否为 X 分配新的内存空间(内存使用情况* 2)?

2 个答案:

答案 0 :(得分:3)

NumPy doc可以说明copy构造函数的array参数:

  

如果为true(默认值),则复制对象。否则,仅当数组返回副本,obj是嵌套序列,或者需要副本以满足任何其他要求(dtype,order等)时,才会进行复制。

您提供了一个"其他要求之一",dtype的示例。所以答案是在这种情况下,忽略copy=False,因为必须复制才能将float32内容转换为更高的精度。

答案 1 :(得分:1)

我喜欢运行一些实验来查看我的系统中“真正”发生了什么。这是一个简单的脚本:

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的结果会产生类似的结果。

进程的已删除内存是否实际返回到系统堆栈是另一回事。