简体   繁体   English

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

[英]Memory allocation for numpy.array with copy=False?

If the type of X is numpy.array with dtype='f4' 如果X的类型为numpy.array ,且dtype ='f4'

Then what is the memory behavior of the line below: 那么下面这行的存储行为是什么:

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

Does it allocate new memory space for X (Memory usage * 2)? 是否为X分配新的内存空间(内存使用率* 2)?

The NumPy doc has this to say about the copy argument to the array constructor: NumPy文档中有关于array构造函数的copy参数的说法:

If true (default), then the object is copied. 如果为true(默认值),则复制对象。 Otherwise, a copy will only be made if array returns a copy, if obj is a nested sequence, or if a copy is needed to satisfy any of the other requirements (dtype, order, etc.). 否则,仅当array返回一个副本,obj是一个嵌套序列,或者需要满足其他任何要求(dtype,order等)的副本时,才创建副本。

You have provided an example of one of the "other requirements", dtype . 您提供了“其他要求”之一dtype的示例。 So the answer is that in this case, copy=False is ignored, because a copy must be made to cast the float32 content into higher precision. 因此答案是,在这种情况下, copy=False被忽略,因为必须进行复制才能将float32内容转换为更高的精度。

I like to run little experiments to see what "really" happens in my system. 我喜欢进行一些小实验,以查看系统中实际发生了什么。 Here's a simple script: 这是一个简单的脚本:

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()

And the output when profiling with python -m memory_profiler ./testProc.py is: 使用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)

As Joe pointed out, the memory profiler's result looks surprising. 正如Joe指出的那样,内存分析器的结果看起来令人惊讶。 The profiler is showing memory allocation after each line. 探查器在每行之后显示内存分配。 The memory footprint enlarges after the lines that fill the arrays, and shrinks when they are deleted. 在填充阵列的行之后,内存占用量会增加,而在删除它们时会缩小。 Results from running ps at the shell give a similar result. 在外壳上运行ps结果给出了相似的结果。

Whether the process's deleted memory actually returns to the system stack is another matter. 进程的已删除内存是否实际返回系统堆栈是另一回事。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM