You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何存储NumPy数组会导致迭代时内存占用持续攀升?

问题:存储NumPy数组导致内存占用累积的原因分析

我遍历asm文件列表,提取数组后关闭文件。此前遇到的内存占用问题现已解决:最初将提取的NumPy数组存入列表时,每次迭代内存占用不断累积;改为先调用tolist()转成Python列表再存入后,问题得以解决。现咨询为何存储NumPy数组会引发该内存问题。

代码如下:

t1_start = process_time() 

files = os.listdir('asmFiles')
i_arrays=[]
file_names=[]
for i in tqdm(files[0:1501]):
    f_name=i.split('.')[0] 
    file_names.append(f_name)
    b='asmFiles/'+str(i)
    f=open(b,'rb')
    ln=os.path.getsize(b)
    width=int(ln**0.5)
    rem=ln%width
    a = array.array("B")
    a.fromfile(f,ln-rem)
    f.close()
    g=np.reshape(a,(int(len(a)/width),width))
    g=np.uint(g)
    h=g[0][0:800]
    i_arrays.append(h.tolist())
print(psutil.virtual_memory()[2])

t1_stop = process_time()
print("Elapsed time during the whole program in seconds:",t1_stop-t1_start)  

原因分析

  1. NumPy数组的视图特性是核心问题
    NumPy的切片操作默认返回的是原数组的视图,而非数据副本。也就是说你代码里的h = g[0][0:800]并没有复制g的前800个元素,只是创建了一个指向g底层内存块的"窗口"。当你把h存入列表i_arrays时,相当于保留了对整个g数组的间接引用——哪怕循环结束后局部变量g被销毁,只要h还在列表里,g的完整内存块就不会被垃圾回收。

  2. NumPy数组的内存结构导致无法及时释放
    NumPy数组由两部分组成:存储元数据(形状、数据类型等)的Python对象,以及存储实际数据的C风格连续内存块。列表中存储的是NumPy数组对象的引用,只要这个引用存在,对应的C内存块就会被锁定,无法被系统回收。而你处理的每个asm文件转换后的g数组体积不小,1500次迭代下来,累积的未释放内存自然会导致占用飙升。

  3. Python列表切断了内存引用链
    调用h.tolist()时,会把NumPy数组的元素逐个转换成Python原生整数,并生成一个独立的Python列表。这个操作会创建数据的完整副本,彻底切断了和原数组g的视图关联。循环结束后,g没有任何引用指向它,就能被Python垃圾回收器及时清理,释放掉大内存块。虽然单个Python整数的内存开销比NumPy的uint8大,但你只保留了800个元素,整体内存占用完全可控。


额外优化建议

  • 如果想继续使用NumPy数组而不转成Python列表,可以在切片时显式创建副本:h = g[0][0:800].copy(),这样就能切断和g的视图关联,让g的内存可以被及时回收。
  • 处理超大asm文件时,可考虑分块读取转换,避免一次性加载整个文件到内存。

内容的提问来源于stack exchange,提问作者Zerorad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 15:15:40