HDF5:存储NumPy数据

2 投票
3 回答
6609 浏览
提问于 2025-04-16 06:47

我在使用NumPy的时候,把数据存储成了*.npy这种原生格式。这种格式非常快,并且给我带来了很多好处,比如:

  • 我可以从C代码中读取*.npy文件,像读取简单的二进制数据一样(也就是说,*.npy文件和C语言的数据结构是兼容的)

现在我在处理HDF5(目前使用的是PyTables)。我在教程中看到,他们使用NumPy的序列化工具来存储NumPy的数据,这样我能像读取简单的*.npy文件一样,从C中读取这些数据吗?

HDF5的NumPy数据也和C语言的数据结构兼容吗?

更新:

我有一个Matlab客户端可以从HDF5读取数据,但我不想从C++读取HDF5,因为从*.npy读取二进制数据要快得多。所以我真的需要从C++读取HDF5(需要二进制兼容性)。

所以我现在使用两种方式来传输数据——*.npy(从C++以字节方式读取,从Python直接读取)和HDF5(从Matlab访问)。如果可以的话,我想只使用一种方式——HDF5,但为了做到这一点,我需要找到一种方法,让HDF5和C++的数据结构兼容。请帮帮我,如果有办法关闭HDF5的压缩或者其他什么方法让HDF5和C++的数据结构兼容,请告诉我我可以在哪里找到相关信息……

3 个回答

0

HDF5会帮你处理结构的二进制兼容性。你只需要告诉它你的结构体包含什么(也就是数据类型),这样在保存和读取记录数组时就不会有问题了。这是因为numpy和HDF5之间的类型系统基本上是一一对应的。如果你使用H5py,我可以很自信地说,只要你使用所有原生类型,并且进行大批量的读写,输入输出的速度应该是足够快的,整个数据集都是可以的。之后的速度就取决于数据的分块和你使用的过滤器(比如洗牌、压缩等)。值得注意的是,有时候这些过滤器可以通过大幅减少文件大小来加速,所以一定要查看基准测试。请注意,类型和过滤器的选择是在创建HDF5文档的那一端做的。

如果你试图自己解析HDF5,那你就是走错了路。要是你在用C++或C,应该使用它们的API。HDF5小组网站上有所谓“复合类型”的示例。

9

从C语言读取hdf5文件的正确方法是使用hdf5的API,具体可以参考这个教程。理论上,如果你的hdf5文件没有使用像压缩这样的高级存储选项,是可以直接读取hdf5文件里的原始数据,就像读取.npy文件一样。不过,这样做其实违背了使用hdf5格式的初衷,我想不出这样做有什么好处,为什么不直接使用hdf5的API呢?另外,API还有一个简化的高级版本,这样从C语言读取数据会相对简单一些。

1

我能理解你的感受。我之前也处理过大量存储在HDF5格式文件中的数据,积累了一些你可能会觉得有用的信息。

如果你能“控制”文件的创建(也就是说,你在写数据,即使是通过API),那么你基本上可以完全绕过HDF5库。

如果你的输出数据集没有被分块,它们会连续写入。只要你在数据类型定义中没有指定任何字节顺序转换(也就是说,你指定的数据应该以本地的浮点数/双精度数/整数格式写入),你就可以实现你所说的“二进制兼容性”。

为了解决我的问题,我写了一个HDF5文件解析器,使用了文件规范,链接在这里:http://www.hdfgroup.org/HDF5/doc/H5.format.html

通过一个相对简单的解析器,你应该能够找到任何数据集的偏移量和大小。到那时,只需使用fseek和fread(在C语言中,也许在C++中有更高级的方法可以使用)。

如果你的数据集是分块的,那么就需要更多的解析工作来遍历用于组织这些块的b树。

你还需要注意的另一个问题是处理任何(或消除)系统相关的结构填充。

撰写回答