Sea*_*708 3 python memory numpy
$ python3
Python 3.5.2 (default, Nov 12 2018, 13:43:14)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def mem():
... with open("/proc/{}/status".format(os.getpid())) as f:
... for line in f:
... if 'VmRSS' in line:
... return line.strip()
...
>>> import gc
>>> import numpy
>>> import os
>>> numpy.version.version
'1.16.4'
>>> print(mem())
VmRSS: 27000 kB
>>> a = [numpy.random.random(size=(128, 128)) for _ in range(5000)]
>>> print(mem())
VmRSS: 668876 kB
>>> gc.collect()
0
>>> print(mem())
VmRSS: 668876 kB
>>> a = None
>>> print(mem())
VmRSS: 455432 kB
>>> gc.collect()
0
>>> print(mem())
VmRSS: 455432 kB
>>> del a
>>> print(mem())
VmRSS: 455432 kB
>>> gc.collect()
0
>>> print(mem())
VmRSS: 455432 kB
Run Code Online (Sandbox Code Playgroud)
在上面的代码片段中,我分配了大约 600MB 的中等大小的 numpy 数组(当数组明显更小或更大时不会发生这种行为,如果只使用 Python 对象则不会发生这种行为),但是当我释放数组时它仍然挂在超过三分之二的内存上,并且没有多少强制垃圾收集或删除会将这些内存返回给操作系统。
我相当确定这不是 numpy 中的内存泄漏,因为新的 numpy 分配将重用该内存(尽管 Python 分配不会),那么任何人都可以阐明为什么会发生这种情况?
编辑:看起来这至少部分与系统分配器有关:
$ LD_PRELOAD=/tmp/tmp.Rl0Ofo69sZ/jemalloc-5.2.1/lib/libjemalloc.so python3
Python 3.5.2 (default, Nov 12 2018, 13:43:14)
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> def mem():
... with open("/proc/{}/status".format(os.getpid())) as f:
... for line in f:
... if 'VmRSS' in line:
... return line.strip()
...
>>> import numpy
>>> import os
>>> print(mem())
VmRSS: 33040 kB
>>> a = [numpy.random.random(size=(128, 128)) for _ in range(5000)]
>>> print(mem())
VmRSS: 694912 kB
>>> a = None
>>> print(mem())
VmRSS: 159568 kB
Run Code Online (Sandbox Code Playgroud)
我目前将其余部分归结为无聊的旧内存碎片,但知道这里是否还有其他事情会很有趣(numpy 似乎确实做了一些它自己的基本缓存)。
小智 5
Numpy 是一个 C 扩展,它管理自己的内存,所以不涉及 Python 的垃圾收集器。Numpy 将使用 malloc() 或 calloc() 为其在堆上的数组分配空间,并在完成后使用 free() 释放该空间(这发生在您设置时a = None)。堆分配器不一定会在空闲时将内存释放回操作系统(),但是,是否发生这种情况取决于如何从操作系统获取内存以及堆碎片等。但是该内存可以正如您所观察到的,仍然会被流程重用。
| 归档时间: |
|
| 查看次数: |
145 次 |
| 最近记录: |