4.5 过滤器和压缩
如果你想要压缩一个连续存储数据集,你立刻会意识到每当你写入一个元素,你都不得不解压并重新压缩整个数据集。这是因为没有什么简单的方法可以让你像对一个非压缩数据集进行偏移量索引那样索引一个压缩数据集。毕竟,压缩以后输出的长度取决于你实际输入的内容。而使用分块存储,你就可以透明地对数据集进行压缩。每个分块的初始大小是已知的,而且由于我们用一个B树来对分块进行索引,我们可以将这些分块随意地放在文件的任何位置,而不是一个接一个地保存。也就是说,每个分块都可以随意扩张或缩小,而不会影响其余分块。
4.5.1 过滤器流水线
HDF5拥有一个过滤器流水线的概念,它实质上是在写入时对每个分块进行一系列的操作。每个过滤器都可以对分块中的数据做任何事情:压缩、计算校验和、添加元数据等任何事。文件被读取时,每个过滤器以反向模式运行来重新构建原始数据。
图4-3展示了过滤器流水线的工作原理图。你会注意到因为数据的最小单位是分块,读写任何数据(哪怕就一个元素)也会导致解压至少一整个分块。在选择分块形状时需要记住这一点,不然你就需要重新考虑你的应用程序是否需要使用压缩。
图4-3 HDF5数据流水线,展示了一个数据集上添加了GZIP和SHUFFLE过滤器
最后,你必须在创建数据集时指定你的过滤器,它们无法被改变。
4.5.2 压缩过滤器
HDF5有许多压缩过滤器。目前应用最广泛的是“GZIP”过滤器。(也有人称其为“DEFLATE”过滤器。在HDF5的世界里,两者指的是同一个过滤器。)
下面是一个浮点数据集使用GZIP压缩的例子:
最棒的是,gzip压缩可以应用于所有固定长度的HDF5类型,而不仅仅是数值类型。
压缩过程是透明进行的,数据可以被正常读写:
调查Dataset对象,我们会发现一些额外的属性:
compression_opts属性(也是调用create_dataset时相应的关键字)反映了压缩过滤器用到的设置。在这个例子里,GZIP默认的压缩级别是4。
你会注意到自动分块器为我们选择了一个形状为(63, 125)的分块。数据被打碎到63×125×(4个字节)=30KB的分块进行压缩。
下面介绍一些常见的压缩过滤器及其细节。
提示
HDF5已有很多过滤器,今后还会有更多。如果你打算归档或跟别人共享一些数据,你最好只使用GZIP、SHUFFLE和FLETCHER32等基本过滤器,因为HDF5自身就包含了它们。
4.5.3 GZIP/DEFLATE压缩器
我们刚刚看到,GZIP压缩器是HDF5目前最简单最可移植的压缩器。每一个HDF5安装版都包含了它。还具有下述优点:
支持HDF5所有的类型;
HDF5内建,到处可用;
适用于慢速压缩;
和SHUFFLE同时使用可提升性能(见48页,SHUFFLE过滤器)。
对于GZIP压缩器来说,compression_opts可以是一个0到9的整数,默认为4。
你也可以直接为compression指定一个数值参数来使用GZIP压缩器:
4.5.4 SZIP压缩器
SZIP是NASA的专利压缩技术。一般你不会用到它,除非你需要跟别人交流卫星数据文件。由于专利许可限制,很多HDF5安装版禁用了SZIP压缩器(但没有禁用SZIP解压器)。
SZIP压缩器的特点:
仅支持(1、2、4、8字节,有符号/无符号)整型和浮点(4/8字节)类型;
快速压缩解压;
解压器几乎总是可用;
由于专利原因,某些发行版(包括Windows上的h5py)不包含压缩器。
4.5.5 LZF压缩器
如果你只用Python处理文件,LZF是一个很好的选择。它跟h5py一起发布。它的C代码在BSD许可下开源,可供第三方程序使用。它的优化为它带来了超高速的压缩,代价则是比GZIP稍低的压缩比。当你的数据集包含大量冗余的数据点时,它是最佳选择。这个过滤器没有compression_opts。
LZF压缩器的特点:
支持HDF5所有的类型;
超快的压缩和解压;
仅可用于Python(和h5py一起发布)。C代码开源。
4.5.6 性能
按惯例,你需要自己做性能测试来确认你的应用程序哪里需要性能提升。不过,这里有一些例子告诉你各种过滤器适用的地方。这个实验(细节见http://h5py.org/lzf)在一个4MB单精度浮点数据集上测试了LZF、GZIP和SZIP压缩器。使用的分块大小是190KB。
首先,数据元素的值等于其索引值(见表4-1):
表4-1 压缩简单数据
压缩器 | 压缩时间(毫秒) | 解压时间(毫秒) | 压缩率 |
None | 10.7 | 6.5 | 0.00% |
LZF | 18.6 | 17.8 | 96.66% |
GZIP | 58.1 | 40.5 | 98.53% |
SZIP | 63.1 | 61.3 | 72.68% |
接下来,测试一个正弦波加随机噪声(见表4-2):
表4-2 压缩噪声数据
压缩器 | 压缩时间(毫秒) | 解压时间(毫秒) | 压缩率 |
None | 10.8 | 6.5 | 0.00% |
LZF | 65.5 | 24.4 | 15.54% |
GZIP | 298.6 | 64.8 | 20.05% |
SZIP | 115.2 | 102.5 | 16.29% |
最后,使用随机浮点值(见表4-3):
表4-3 压缩随机浮点数据
压缩器 | 压缩时间(毫秒) | 解压时间(毫秒) | 压缩率 |
None | 9.0 | 7.8 | 0.00% |
LZF | 67.8 | 24.9 | 8.95% |
GZIP | 305.4 | 67.2 | 17.05% |
SZIP | 120.6 | 107.7 | 15.56% |
再次提醒,不要将这些图表当成普适真理。有些过滤器(比如说BLOSC,参见4.7节)甚至比LZF更快。何况应用程序很少会把大多数时间耗费在压缩解压数据上,所以不要被速度测试蒙蔽了你的智慧。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论