从 HDF5 文件中删除数据

Posted

技术标签:

【中文标题】从 HDF5 文件中删除数据【英文标题】:Removing data from a HDF5 file 【发布时间】:2010-11-10 15:11:17 【问题描述】:

我有一个 HDF5 文件,其中包含复合元素的一维 (N x 1) 数据集 - 实际上它是一个时间序列。数据首先离线收集到 HFD5 文件中,然后进行分析。在分析过程中,大多数数据被证明是无趣的,只有部分数据是有趣的。由于数据集可能非常大,我想去掉不感兴趣的元素,同时保留有趣的元素。例如,保留 500 个元素数据集的 0-100 和 200-300 和 350-400 元素,转储其余元素。但是怎么做呢?

有人对如何使用 HDF5 完成此任务有经验吗?显然,它至少可以通过多种方式完成:

(明显的解决方案),创建一个新文件并在其中逐个元素地写入必要的数据。然后删除旧文件。 或者,在旧文件中,创建一个新的新数据集,在其中写入必要的数据,使用 H5Gunlink() 取消链接旧数据集,并通过 h5repack 运行文件来清除未声明的可用空间。 或者,将现有数据集中的有趣元素移向开头(例如,将元素 200-300 移动到位置 101-201,将元素 350-400 移动到位置 202-252)。然后调用 H5Dset_extent() 来减小数据集的大小。然后可能会运行 h5repack 以释放可用空间。

由于即使删除了无趣的元素,文件也可能相当大,我宁愿不重写它们(这需要很长时间),但似乎需要实际释放可用空间。来自 HDF5 专家的任何提示?

【问题讨论】:

【参考方案1】:

HDF5(至少我习惯的版本,1.6.9)不允许删除。实际上,确实如此,但它不会释放已用空间,结果您仍然有一个巨大的文件。如您所说,您可以使用 h5repack,但这是浪费时间和资源。

您可以做的就是拥有一个包含布尔值的横向数据集,告诉您哪些值是“活动的”,哪些值已被删除。这不会使文件变小,但至少它为您提供了一种快速执行删除的方法。

另一种方法是在你的数组上定义一个slab,复制相关数据,然后删除旧数组,或者总是通过slab访问数据,然后根据需要重新定义它(虽然我从来没有这样做过,所以我不确定是否可能,但应该)

最后,您可以使用 hdf5 挂载策略将数据集放在您挂载在根 hdf5 上的“附加”hdf5 文件中。当你想删除这些东西时,将感兴趣的数据复制到另一个挂载的文件中,卸载旧文件并将其删除,然后将新文件重新挂载到适当的位置。此解决方案可能会很混乱(因为您有多个文件),但它允许您释放空间并仅对数据树的子部分进行操作,而不是使用重新打包。

【讨论】:

感谢您的想法。它确实可以通过多种方式完成。希望有一天真正的删除功能将添加到 HDF5 中,不得不像这样乱七八糟地删除东西几乎是荒谬的......但除此之外,这是一个很好的文件格式:-) 删除和打包并不容易。 HDF5 就像一个文件系统。即使您释放块,将它们标记为已删除,在“实时”时打包文件也很困难,并且是性能瓶颈。你在 MacOSX 上的加密文件系统面临同样的问题,所以我猜我不希望将来任何时候都能在 HDF5 级别解决你的问题。 诚然,这确实不容易,也许不是 HDF5 开发人员的主要兴趣所在。但这肯定是可能的——我认为大多数数据库都可以做到。 好吧,在 PostgreSQL 中,你有 VACUUM 命令可以做到这一点,并且通常不时手动调用它。【参考方案2】:

不幸的是,复制数据或使用 h5repack 是在 HDF5 文件中“缩小”数据的两种常用方法。

您可能已经猜到,问题在于 HDF5 文件具有复杂的内部结构(文件格式为 here,任何好奇的人都可以使用),因此删除和缩小文件只会在相同的文件中留下漏洞——大小的文件。 HDF5 库的最新版本可以跟踪释放的空间并重新使用它,但您的用例似乎无法利用这一点。

正如另一个答案所提到的,您也许可以使用外部链接或虚拟数据集功能来构建更适合您将要执行的操作的 HDF5 文件,但我怀疑您仍然会复制大量数据,这肯定会增加额外的复杂性和文件管理开销。

顺便说一句,H5Gunlink() 已被弃用。 H5Ldelete() 是首选替代方法。

【讨论】:

以上是关于从 HDF5 文件中删除数据的主要内容,如果未能解决你的问题,请参考以下文章

使用 h5py 删除 hdf5 数据集

将更多数据集附加到现有 Hdf5 文件中,而不删除其他组和数据集

有没有办法从 HDF5 数据集中删除行?

从 HDF5 文件中删除信息

无法从自制软件安装 hdf5 库

如何从 C++ 中的 hdf5 文件中读取数据块?