HDF5存储开销

10
我正在将大量小数据集写入HDF5文件,结果的文件大小是我从数据简单列出的期望大小的10倍。我的数据按照以下层次结构组织:
group 0
    -> subgroup 0
        -> dataset (dimensions: 100 x 4, datatype: float)
        -> dataset (dimensions: 100, datatype: float)
    -> subgroup 1
        -> dataset (dimensions: 100 x 4, datatype: float)
        -> dataset (dimensions: 100, datatype: float)
    ...
group 1
...

每个子组应该占用 500 * 4 字节 = 2000 字节,忽略开销。我没有存储数据旁边的任何属性。然而,在测试中,我发现每个子组大约占用了 4 kB 的空间,大约是我预期的两倍。我知道有一些开销,但是它来自哪里?如何减少它?它与表示组结构有关吗?
更多信息: 如果我将每个子组中两个数据集的维度增加到 1000 x 4 和 1000,则每个子组占用的空间约为 22,250 字节,而不是我预期的平坦的 20,000 字节。这意味着每个子组的开销为 2.2 kB,并且与较小的数据集大小得到的结果一致。有没有办法减少这种开销?

3
HDF5文件格式非常复杂,它使用内部分块来存储数据和元数据对象。默认的元数据块大小为2 KiB,并且每个(子)组都有自己的头部空间,这就解释了大约2000字节的观察差异。您可以尝试使用“压缩(COMPACT)”存储进行实验,有关存储策略的更多信息,请参见这里(http://www.hdfgroup.org/HDF5/doc1.6/UG/10_Datasets.html)的(4.5)部分。 - Hristo Iliev
2
我上面提供的数字是基于COMPACT设置的。从中得到的教训是要避免将少量数据放在复杂的群组结构中。将所有数据集合并到一个较大的数组中并进行压缩后,我获得了超过1:1的打包比率(压缩节省的空间比HDF5开销增加的空间更多)。 - apdnu
@Thucydides411,你的评论是最佳答案!你应该将其写成一个答案并接受它。 - Simon
2个回答

6
我来回答自己的问题。在表示组结构方面涉及到的开销足以说明不存储小数组或包含少量数据的许多组是没有意义的。似乎没有任何方法可以减少每个组的开销,我测得为约2.2 kB。
我通过将每个子组中的两个数据集合并成一个(100x5)的数据集来解决了这个问题。然后,我消除了子组,并将每个组中的所有数据集合并成一个3D数据集。因此,如果之前有N个子组,则现在每个组中只有一个数据集,形状为(N x 100 x 5)。我因此节省了之前存在的N * 2.2 kB开销。此外,由于HDF5内置的压缩对较大的数组更有效,因此现在得到了超过1:1的整体压缩比率,而以前,开销占据了文件的一半空间,压缩完全无效。
教训是要避免在HDF5文件中使用复杂的组结构,并尽可能将尽可能多的数据合并到每个数据集中。

3
是的,也不完全是。HDF5是由科学家创建的用于存储大型数据集的库。我认为过于关注2Kb会忽略了重点。如果空间非常受限,那么这可能不是适合您的库。尽可能使数据自我描述始终是值得的,即使需要一些 Kb 来实现。您可以构建“聪明”的数据结构,就像您可以编写“聪明”的代码一样,但是摩尔定律支持那些编写可维护代码和自我描述数据结构的人。 - Ewan Makepeace
1
我认为我在我的答案中已经解释过了。如果您存储大量小数据集,每个数据集2kB肯定是一个问题。我的建议是将数据尽可能地打包到更大的数据集中。我没有提出复杂的结构:一个具有意义的三维数据集非常简单,其中每个轴都有一个含义。 - apdnu
考虑使用 JSON 或二进制 JSON 来处理此类数据,与 HDF5 相比,它更具可移植性和多功能性。如果需要使用 JSON 存储科学数据结构(如 ND-arrays、表格),请考虑使用 JData 注释。 - FangQ

0

最近在这个方向上进行了一些工作,1.10.5中可用。现在有一个名为H5Fset_dset_no_attrs_hint的函数,它设置文件或数据集属性创建列表,以便在对象头中不分配太多空间。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接