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

如何将42000个numpy数组列表保存到磁盘?解决内存不足问题

嘿,我之前也碰到过这种超大numpy列表存不下的头疼问题,给你几个亲测有效的解决方案,肯定能帮你搞定内存瓶颈!

方案1:用h5py增量写入(最推荐,内存友好)

你之前以为HDF5不能存列表其实是个小误解!h5py完全支持逐个写入数组,不需要一次性把所有数据塞进内存,完美适配你的16GB内存情况。

实现步骤:

  1. 导入h5py库(如果没装先跑pip install h5py)
  2. 打开一个HDF5文件,用写模式
  3. 循环遍历你的数组列表,给每个数组分配一个带编号的数据集名称(比如arr_00000)
  4. 逐个写入数组,每次只占用单个数组的内存,写完就释放
import h5py
import numpy as np

# 假设你的数组列表叫arr_list
arr_list = [np.random.rand(240,240) for _ in range(42000)]  # 替换成你的真实数据

with h5py.File('large_data.h5', 'w') as f:
    for idx, arr in enumerate(arr_list):
        # 用格式化字符串命名,保证索引有序,方便后续读取
        f.create_dataset(f'arr_{idx:05d}', data=arr, compression='gzip')

读取方式(按需加载,不占内存):

with h5py.File('large_data.h5', 'r') as f:
    # 读取第100个数组(索引从0开始)
    arr_100 = f['arr_00100'][()]
    
    # 或者遍历所有数组处理
    for key in sorted(f.keys()):
        arr = f[key][()]
        # 这里写你的处理逻辑
方案2:用Zarr分块存储(更灵活的大数据格式)

Zarr是专门为超大数组设计的格式,支持分块压缩,内存占用极低,而且用法几乎和numpy一模一样,非常适合深度学习场景。

实现步骤:

  1. 安装zarr:pip install zarr
  2. 创建一个zarr数组,设置好总形状和分块大小(比如每个分块对应1个240x240的数组)
  3. 逐个写入数组,内存只占用单个数组的空间
import zarr
import numpy as np

arr_list = [np.random.rand(240,240) for _ in range(42000)]

# 创建zarr数组,总形状(42000,240,240),分块设为(1,240,240),启用gzip压缩
zarr_arr = zarr.open('large_data.zarr', mode='w', shape=(42000,240,240), chunks=(1,240,240), compression='gzip')

# 逐个写入,完全不占额外内存
for idx, arr in enumerate(arr_list):
    zarr_arr[idx] = arr

读取方式:

zarr_arr = zarr.open('large_data.zarr', mode='r')
# 直接索引读取,比如第500个数组
arr_500 = zarr_arr[500]
# 甚至可以像numpy一样切片:zarr_arr[100:200] 读取第100-199个数组
方案3:分拆成多个压缩NPZ文件(简单粗暴易上手)

如果不想学新库,这个方法最直接——把大列表拆成小批次,每个批次存一个npz文件,单个文件内存压力小,不会触发内存错误。比如每1000个数组存一个文件:

import numpy as np

arr_list = [np.random.rand(240,240) for _ in range(42000)]
batch_size = 1000  # 可以根据你的内存情况调整批次大小

for i in range(0, len(arr_list), batch_size):
    batch = arr_list[i:i+batch_size]
    # 把批次里的数组存成字典
    batch_dict = {f'arr_{j}': arr for j, arr in enumerate(batch)}
    # 压缩保存
    np.savez_compressed(f'data_batch_{i//batch_size:02d}.npz', **batch_dict)

读取方式:

# 加载第3个批次(索引从0开始)
batch_data = np.load('data_batch_02.npz')
# 获取批次里的第50个数组
arr = batch_data['arr_50']
为什么之前的方法会失败?
  • pickle和numpy.savez_compressed:这俩都需要把所有数据一次性加载到内存,再压缩写入。你的42000个240x240数组(如果是float32)总内存约9.2GB,加上压缩过程的临时内存,很容易超过16GB触发内存错误。
  • 单个大numpy数组:虽然总大小2.3GB(应该是用了uint8类型?),但处理时频繁切片、复制会产生大量临时内存,导致电脑崩溃。

总结下,h5py和zarr是最优解,支持增量写入/按需读取,完全不占额外内存;分拆NPZ是快速实现的备选方案,适合不想折腾新库的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 04:07:17