从HDF5文件中删除数据

17
我有一个带有一维(N x 1)复合元素数据集的HDF5文件 - 实际上它是一个时间序列。 数据首先离线收集到HFD5文件中,然后进行分析。 在分析过程中,大部分数据都不重要,只有其中一些部分是重要的。 由于数据集可能相当大,因此我想摆脱不相关的元素,同时保留感兴趣的元素。 例如,保留500个元素数据集的元素0-100、200-300和350-400,并丢弃其余部分。 但如何操作?
有人使用HDF5完成这项工作吗? 显然有几种方法可以实现:
1. (显而易见的解决方案)创建一个新文件,并逐个元素将必要的数据写入其中。 然后删除旧文件。 2. 或者,在旧文件中创建一个新的数据集,并在那里写入必要的数据。 使用H5Gunlink()取消关联旧数据集,通过运行h5repack来摆脱未声明的空闲空间。 3. 或者,将现有数据集中的有趣元素移动到开始位置(例如,将元素200-300移动到位置101-201并将元素350-400移动到位置202-252)。 然后调用H5Dset_extent()来减少数据集的大小。 然后可能需要运行h5repack以释放空闲空间。
由于即使删除不相关的元素后文件仍可能相当大,因此我宁愿不重写它们(这需要很长时间),但似乎必须实际释放空闲空间。 HDF5专家有何提示?
2个回答

9
HDF5(至少我使用的版本1.6.9)不允许删除。实际上,它是可以删除的,但它不会释放已用空间,结果你仍然有一个巨大的文件。正如你所说,你可以使用h5repack,但这是浪费时间和资源。
你可以做的一件事是有一个侧面数据集包含一个布尔值,告诉你哪些值是“活着”的,哪些已被删除。这并不能使文件变小,但至少它给你一个快速的方法来执行删除。
另一种选择是在数组上定义一个slab,复制相关数据,然后删除旧数组,或者总是通过slab访问数据,然后根据需要重新定义它(虽然我从未这样做过,所以我不确定它是否可行,但应该是可行的)。
最后,你可以使用hdf5挂载策略,在你的根hdf5上挂载一个“附加”hdf5文件中的数据集。当你想要删除东西时,将有趣的数据复制到另一个挂载的文件中,卸载旧文件并删除它,然后在适当的位置重新挂载新文件。这个解决方案可能有点混乱(因为你周围有多个文件),但它允许你释放空间,并且只对你的数据树的子部分进行操作,而不是使用repack。

谢谢您的想法。确实有很多方法可以做到这一点。希望 HDF5 以后能够添加真正的删除功能,因为像这样乱搞来删除东西几乎是荒谬的...但除此之外,它是一个很好的文件格式 :-) - Joonas Pulakka
1
删除和压缩并不容易。HDF5就像一个文件系统。即使您释放了块并将它们标记为已删除,但在“运行”时压缩文件仍然很困难且会影响性能。您在MacOSX上加密文件系统时也会面临同样的问题,因此我猜测未来在HDF5层面上解决您的问题可能性不大。 - Stefano Borini
没错,这确实不容易,也许对于HDF5开发人员来说并不是主要的兴趣点。但是这肯定是可能的 - 大多数数据库都可以做到,我想。 - Joonas Pulakka
在PostgreSQL中,您可以使用VACUUM命令来完成这项工作,通常需要手动定期调用。 - Stefano Borini

3
复制数据或按照您所描述的使用h5repack是“压缩”HDF5文件数据的两种常见方式,但不幸的是,HDF5文件具有复杂的内部结构(有关文件格式的信息在此处),因此删除和收缩会留下一个相同大小的文件中的空洞。最近版本的HDF5库可以跟踪空闲空间并重复使用它,但您的用例似乎无法利用这一点。
正如其他回答所提到的,您可能能够使用外部链接或虚拟数据集功能来构建更适合进行操作的HDF5文件,但我怀疑您仍然需要复制大量数据,并且这肯定会增加额外的复杂性和文件管理开销。
顺便说一句,H5Gunlink()已被弃用。 H5Ldelete()是首选替代方法。

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