首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >(Python/h5py)内存-高效处理HDF5数据集切片

(Python/h5py)内存-高效处理HDF5数据集切片
EN

Stack Overflow用户
提问于 2022-09-20 19:00:39
回答 1查看 114关注 0票数 0

我在python中使用的是一个大型的图像数据集,每个数据集都是3600x1800。总共有360000幅图像。每个图像被一个一个地添加到堆栈中,因为每个图像上都运行了一个初始处理步骤。事实证明,H5py在不填充整个内存的情况下,能够有效地构建逐个图像的堆栈。

我正在运行的分析是在网格单元上计算的--例如堆栈的1x1x360000片。由于每个切片的分析取决于该片内的最大值和最小值,所以我认为有必要将360000长的数组保存在内存中。我有相当一部分RAM要处理(~100 of ),但不足以同时将3600x1800x360000的整个堆栈存储在内存中。

这意味着我需要(或者我认为我需要)一种访问360000长数组的高效方法。虽然h5py有效地将每个图像添加到堆栈中,但是垂直于图像的切片看起来要慢得多(小时或更长)。

我是不是缺少一种明显的方法来分割垂直于图像的数据?

下面的代码是两个不同切片方向的计时基准:

代码语言:javascript
复制
file = "file/path/to/large/stack.h5"

t0 = time.time()
with h5py.File(file, 'r') as f:
    dat = f['Merged_liqprec'][:,:,1]
    
print('Time = ' + str(time.time()- t0))

t1 = time.time()
with h5py.File(file, 'r') as f:   
    dat = f['Merged_liqprec'][500,500,:]
    
print('Time = ' + str(time.time()- t1))

输出:

代码语言:javascript
复制
## time to read a image slice, e.g. [:,:,1]:
Time = 0.0701  

## time to read a slice thru the image stack, e.g. [500,500,:]:
Time = multiple hours, server went offline for maintenance while running
EN

回答 1

Stack Overflow用户

发布于 2022-09-22 20:40:03

HDF5块存储提高了I/O时间,但在读取小片(例如[1,1,360000])时仍然非常慢。为了进一步提高性能,您需要像@Jér me Richard在下面的注释中描述的那样,将较大的切片读入数组中。然后,您可以从数组中快速访问单个切片(因为它在内存中)。

这个答案结合了两种技术: 1) HDF5块存储(来自我的第一个答案);2)将大片读取到数组中,然后从该数组读取单个[i,j]片。创建文件的代码非常类似于第一个答案。它的设置是创建一个默认块大小(我的系统上的[3600, 1800, 100] )形状[113, 57, 7]的数据集。可以增加n以使用更大的数据集进行测试。

在读取文件时,将大片和1维设置为关联的块形状(因此我只访问每个块一次)。因此,读取文件的过程“稍微复杂一些”(但值得这样做)。有两个循环:第一个循环将一个大片读取到一个数组'dat_chunk'‘,第二个循环将一个[1,1,:]片从'dat_chunk'到第二个数组'dat'中读取。

100幅图像的定时数据差异很大。使用下面的方法读取所有数据需要8秒。第一个答案需要74分钟(直接读取每对[i,j] )。显然这太慢了。为了好玩,我将测试文件和重新运行中的数据集大小增加到1000个图像(shape=[3600, 1800, 1000])。用这种方法读取所有切片需要4:33 (m:ss)。我甚至没有尝试以前的方法(原因很明显)。注意:我的电脑很老了&用HDD很慢,所以你的计时数据应该更快。

创建文件的代码:

代码语言:javascript
复制
a0, a1, n = 3600, 1800, 100
print(f'Writing dataset shape=({a0},{a1},{n})')
start = time.time()
with h5py.File('SO_73791464.h5','w') as h5f:
     ds = h5f.create_dataset('images',dtype=int,shape=(a0,a1,n),chunks=True) 
     print(f'chunks={ds.chunks}')
     for i in range(n):
          arr = np.random.randint(256,size=(a0,a1))
          ds[:,:,i] = arr
 print(f"Time to create file:{(time.time()-start): .3f}")

使用大数组片读取文件的代码:

代码语言:javascript
复制
start = time.time()       
with h5py.File('SO_73791464.h5','r') as h5f:
    ds = h5f['images']
    print(f'shape={ds.shape}')
    print(f'chunks={ds.chunks}')
    ds_i_max, ds_j_max, ds_k_max = ds.shape
    ch_i_max, ch_j_max, ch_k_max = ds.chunks
    
    i = 0
    while i < ds_i_max:
        i_stop = min(i+ch_i_max,ds_i_max)    
        print(f'i_range: {i}:{i_stop}')
        j = 0
        while j < ds_j_max:
            j_stop = min(j+ch_j_max,ds_j_max)    
            print(f'  j_range: {j}:{j_stop}')
            dat_chunk = ds[i:i_stop,j:j_stop,:]
            # print(dat_chunk.shape)
            for ic in range(dat_chunk.shape[0]):
                for jc in range(dat_chunk.shape[1]):
                    dat = dat_chunk[ic,jc,:]
            j = j_stop
        i = i_stop     
              
print(f"Time to read file:{(time.time()-start): .3f}")
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/73791464

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档