Numpy 如何在内存中加载大型h5文件?

Numpy 如何在内存中加载大型h5文件?,numpy,hdfs,hdf5,h5py,chunking,Numpy,Hdfs,Hdf5,H5py,Chunking,我有一个大的h5文件,带有HDFS中的5维numpy数组。文件大小约为130Gb。我在加载文件时遇到内存问题,进程因OOM错误而终止,即使机器有256Gb RAM。如何将文件分块写入并分块加载?我环顾四周,发现h5py提供了这样的方法来对数据集进行分块,但是如何将数据分块加载回数据集呢?如果文件驻留在HDFS中,它也可以工作吗 dset = f.create_dataset("Images2", (100,480,640), 'f', chunks=True) 想法是分批加

我有一个大的h5文件,带有HDFS中的5维numpy数组。文件大小约为130Gb。我在加载文件时遇到内存问题,进程因OOM错误而终止,即使机器有256Gb RAM。如何将文件分块写入并分块加载?我环顾四周,发现h5py提供了这样的方法来对数据集进行分块,但是如何将数据分块加载回数据集呢?如果文件驻留在HDFS中,它也可以工作吗

dset = f.create_dataset("Images2", (100,480,640), 'f', chunks=True)

想法是分批加载文件,以减少I/O时间和内存问题。任何帮助都将不胜感激。

HDF5中的分块意味着数据不是连续存储的,而是分块存储的。 请参阅此处的信息: -->所以这对你的问题没有帮助

解决方案可能是您自己构建一个函数来分块加载数据。 例如,我这样做是为了将数据分块:

def get_chunked(data, chunk_size=100):
    for i in give_chunk(len(data), chunk_size):
        chunked_array = data[i]
        yield chunked_array

def give_chunk(length, chunk_size):
    it = iter(range(length))
    while True:
        chunk = list(itertools.islice(it, chunk_size))
        if not chunk:
            break
        yield chunk
要将数据写入HDF5,可以先创建数据集,然后通过切片写入数据块,请参阅h5py文档:

关于HDF5的基本知识,我真的可以推荐这本书:

上面的答案和评论中提到了两个类似(但不同)的h5py I/O概念:

  • HDF5分块用于启用分块I/O以提高性能。如果在试图读取内存不足的大型数据集时出现OOM错误,分块可能没有帮助
  • NumPy样式切片用于将数据片段从驱动器读取到内存(或将数据片段写入驱动器)。在读取非常大的文件时,切片是避免OOM错误的关键
  • 此外,在创建非常大的数据集时,通常需要 它可以调整大小。您可以分配初始大小,然后使用“.resize()”方法增加磁盘上的大小
我写了一个简单的例子,展示了如何使用切片和分块。它一次将100个图像加载到可调整大小的数据集中。然后它关闭文件并重新打开(只读),一次将100个图像读取到一个NumPy数组中

有效的分块需要适当的大小/形状,并基于阵列形状和I/O需要。我在示例中设置了块大小/形状,以匹配我正在写入/读取的100个图像数组的大小

这个例子应该让你开始学习。您需要修改以使用5-d数组/数据集

import numpy as np
import h5py

with h5py.File('SO_64645940.h5','w') as h5w:
    img_ds = h5w.create_dataset('Images', shape=(100,480,640), dtype='f', maxshape=(None,480,640),chunks=(10,480,640))

    next_img_row = 0    
    arr = np.random.random(100*480*640).reshape(100,480,640)
    for cnt in range(1,10):
#        print(cnt,img_ds.len(),next_img_row)
        if img_ds.len() == next_img_row :
            img_ds.resize(100*cnt,axis=0)
            print('new ds size=',img_ds.len())
        h5w['Images'][next_img_row:next_img_row+100] = arr
        next_img_row += 100
    
    
with h5py.File('SO_64645940.h5','r') as h5r:
     for cnt in range(10):
         print('get slice#',str(cnt))
         img_arr = h5r['Images'][cnt*100:(cnt+1)*100] 

即使没有块,也可以加载片,例如
dset[33]
dset[22:55]
。这在
h5py
文档中有说明。