函数内初始化Numpy数组后内存无法释放的解决办法咨询
解决NumPy数组函数返回后内存未释放的问题
首先得澄清一个常见误解:你用resource.getrusage(resource.RUSAGE_SELF).ru_maxrss获取的是进程自启动以来的最大内存使用量,而非当前内存占用。所以就算内存已经释放,这个值也不会下降——它只记录峰值。你可以通过系统工具(比如Linux的top/ps,Windows的任务管理器)来查看真实的当前内存占用。
接下来,针对NumPy内存看似未释放的问题,本质原因是NumPy使用自己的内存池管理底层C内存,而非完全依赖Python的垃圾回收(GC)机制。下面是几种有效的解决方法:
方法1:手动清理引用+强制GC
这是最基础的方法,先移除数组的引用,再触发Python垃圾回收,让NumPy回收底层内存(虽然可能暂时存在于NumPy的内存池,而非立刻还给操作系统):
import numpy as np import resource import gc def function(): x = np.random.random([10000, 10000]) print('Peak memory inside function: %s (kb)'% resource.getrusage(resource.RUSAGE_SELF).ru_maxrss) # 删除数组引用 del x # 强制触发垃圾回收 gc.collect() function() # 这里的ru_maxrss还是峰值,但实际当前内存已经下降 print('Peak memory after function: %s (kb)'% resource.getrusage(resource.RUSAGE_SELF).ru_maxrss)
方法2:强制NumPy释放内存池
如果需要把内存还给操作系统,可以在GC后触发NumPy内存池的清理。创建一个空数组有时会触发这个操作:
import numpy as np import resource import gc def function(): x = np.random.random([10000, 10000]) print('Peak memory inside function: %s (kb)'% resource.getrusage(resource.RUSAGE_SELF).ru_maxrss) del x gc.collect() # 创建空数组触发内存池清理 np.zeros(0) function() print('Peak memory after function: %s (kb)'% resource.getrusage(resource.RUSAGE_SELF).ru_maxrss)
方法3:系统级内存回收(Linux专属)
如果是在Linux系统上,可以直接调用系统API告诉操作系统回收内存,这会立刻降低当前内存占用:
import numpy as np import resource import gc import posix def function(): x = np.random.random([10000, 10000]) print('Peak memory inside function: %s (kb)'% resource.getrusage(resource.RUSAGE_SELF).ru_maxrss) # 获取数组的内存地址和大小 mem_ptr = x.__array_interface__['data'][0] mem_size = x.nbytes # 告诉操作系统可以回收这块内存 posix.madvise(mem_ptr, mem_size, posix.MADV_DONTNEED) del x gc.collect() function() print('Peak memory after function: %s (kb)'% resource.getrusage(resource.RUSAGE_SELF).ru_maxrss)
补充说明
- NumPy的内存池是一种优化:如果后续还要创建数组,复用内存会比重新向操作系统申请更快,所以很多时候不需要刻意释放内存。
- 如果你在Windows系统上,没有
posix模块,可以尝试使用ctypes调用Windows的内存管理API,不过操作相对复杂,一般推荐方法1和方法2即可。
内容的提问来源于stack exchange,提问作者Ben N
相关产品推荐
相关产品推荐

