h5py で既存の HDF5 ファイルを圧縮した。現状の HDF5 は、既存のデータセットを削除できない(論理的には削除できるが、その領域を再利用できないし、ファイルサイズが縮むこともない)ので、新たにファイルを作って、圧縮フィルタを通しながら書き込んでいくしかない。
以下では、data という名前のデータセットのみ圧縮している。
import h5py import sys if len(sys.argv) != 3: print "Usage: %s inp.h5 out.h5" % sys.argv[0] sys.exit(-1) inp = h5py.File(sys.argv[1], "r") out = h5py.File(sys.argv[2], "w-") def rec(dinp, dout): for k in dinp: print k if dinp[k].__class__ is h5py._hl.group.Group: dout.create_group(k) rec(dinp[k], dout[k]) else: source = dinp[k] compression = None compression_opts = None if k == "data": compression = "gzip" compression_opts = 9 dout.create_dataset(k, shape=source.shape, dtype=source.dtype,\ data=source, compression=compression, compression_opts=compression_opts) rec(inp, out)
とある回折画像を圧縮したところ、サイズは以下のようになった。
設定 | サイズ (byte) | |
---|---|---|
元のファイル | 41955504 | |
gzip opt2 | 20686982 | |
gzip opt4 | 20404798 | |
gzip opt9 | 20174447 | |
lzf | 30444781 |
速度的には、gzip opt9 <約10倍< opt4 〜 opt2 〜 lzf < 無圧縮 という感じ。
このうち、lzf は h5py 附属なので、hdf5lib だけでは使えない。gzip は hdf5lib 標準添付なのでどの環境でも使えはずだが、実際には Anaconda でインストールされる h5py はビルド方法が不適切で、gzip フィルタが使えない(Anaconda 1.7 h5py does not have gzip/deflate filter)。
と、ここまで書いたところで、h5repack ユーティリティで圧縮できることが判明したorz
h5repack の場合、
h5repack -f GZIP=4 input.h5 output.h5
のようになる。
設定 | サイズ (byte) | 所要時間 (sec) |
---|---|---|
元のファイル | 1804225760 | - |
gzip opt2 | 738225990 | 40.3 |
gzip opt4 | 707160027 | 52.4 |
という感じ。