首页 > 解决方案 > 使用 h5py 压缩现有 HDF5 数据集并释放空间,无需复制或使用 h5repack

问题描述

HDF5我想使用 python HDF5 接口对文件中的某些数据集执行“就地”压缩h5py并回收任何可能的空间。

根据我的观察,即使将数据集作为 numpy 数组读取,然后删除 HDF5 中的原始数据集,然后使用写回 HDF5 文件compression='gzip',实际上也不会释放磁盘上的任何空间:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import h5py
import numpy as np
import os
import shutil

data_sngl = np.ones(shape=(100,100,100), dtype=np.float64)*np.pi

# ===== make uncompressed HDF5 for reference

with h5py.File('data_sngl.h5', 'w') as hf:
    hf.create_dataset('data', data=data_sngl, chunks=True)
print('data_sngl.h5 : %0.4f [MB]'%(os.path.getsize('data_sngl.h5')/1000**2))

# ===== make compressed HDF5 for reference

with h5py.File('data_sngl_gz.h5', 'w') as hf:
    hf.create_dataset('data', data=data_sngl, chunks=True, compression='gzip', compression_opts=9, shuffle=True)
print('data_sngl_gz.h5 : %0.4f [MB]'%(os.path.getsize('data_sngl_gz.h5')/1000**2))

# ===== attempt 'in-place' compression

shutil.copy2('data_sngl.h5','data_sngl_bak.h5') ## make a copy

with h5py.File('data_sngl.h5', 'r+') as hf: ## open in read/write mode
    data = np.copy(hf['data'][:])
    del hf['data'] ## deleting dataset!

    ### write with compression opts active
    hf.create_dataset('data', data=data, chunks=True, compression='gzip', compression_opts=9, shuffle=True)

print('data_sngl.h5 : %0.4f [MB] --> after in-place compress'%(os.path.getsize('data_sngl.h5')/1000**2))

# ===== 'repack' the in-place compressed file

os.system('h5repack -i data_sngl.h5 -o data_sngl_repacked.h5')
print('data_sngl_repacked.h5 : %0.4f [MB]'%(os.path.getsize('data_sngl_repacked.h5')/1000**2))

# ===== compress while copying to new file

with h5py.File('data_sngl_bak.h5', 'r') as hf:
    data = np.copy(hf['data'][:])
    with h5py.File('data_sngl_copy.h5', 'w') as hfc:
        hfc.create_dataset('data', data=data, chunks=True, compression='gzip', compression_opts=9, shuffle=True)

print('data_sngl_copy.h5 : %0.4f [MB] --> copy compress'%(os.path.getsize('data_sngl_copy.h5')/1000**2))

未压缩数据的标称大小约为 8.7MB。当最初写入一个新的 hdf5 / 新数据集时,大小要小得多(这是一个理想的压缩情况)。

使用“就地”压缩,这意味着将数据集作为 numpy 数组复制到内存,然后使用 删除数据集del,然后通过压缩将 numpy 数据写回,文件仍然没有明显变小。

如果h5repack在该文件上运行,则空间减少变得可见。

或者,不出所料,如果h5py使用压缩选项简单地将数据集复制到新的 HDF5,那么空间减少也变得可见。

data_sngl.h5 : 8.6793 [MB]
data_sngl_gz.h5 : 0.0505 [MB]
data_sngl.h5 : 7.4656 [MB] --> after in-place compress
data_sngl_repacked.h5 : 0.0441 [MB]
data_sngl_copy.h5 : 0.0505 [MB] --> copy compress

有没有办法避免必须复制到新的 HDF5 或必须从h5repack外部调用?是否有一些技巧h5py可以指示 HDF5 “重新打包”,允许就地压缩/空间重新分配,而无需有效地将 HDF5 的完整内容复制到新文件中?

标签: pythonnumpycompressionhdf5h5py

解决方案


推荐阅读