HDF5 复合类型 Native vs. IEEE

Posted

技术标签:

【中文标题】HDF5 复合类型 Native vs. IEEE【英文标题】:HDF5 Compound type Native vs. IEEE 【发布时间】:2013-02-15 06:20:17 【问题描述】:

我刚开始使用 HDF5,我对为内存创建数据和为文件创建数据之间的区别感到有些困惑。有什么区别?

在this例子中,创建复合类型数据需要在内存中创建数据并放入文件中:

 /*
 * Create the memory data type. 
 */
s1_tid = H5Tcreate (H5T_COMPOUND, sizeof(s1_t));
H5Tinsert(s1_tid, "a_name", HOFFSET(s1_t, a), H5T_NATIVE_INT);
H5Tinsert(s1_tid, "c_name", HOFFSET(s1_t, c), H5T_NATIVE_DOUBLE);
H5Tinsert(s1_tid, "b_name", HOFFSET(s1_t, b), H5T_NATIVE_FLOAT);

/* 
 * Create the dataset.
 */
dataset = H5Dcreate(file, DATASETNAME, s1_tid, space, H5P_DEFAULT);

/*
 * Wtite data to the dataset; 
 */
status = H5Dwrite(dataset, s1_tid, H5S_ALL, H5S_ALL, H5P_DEFAULT, s1);

但是,在另一个示例here 中,作者还为该文件创建了一个复合数据,它指定了不同的数据类型。例如,在为内存创建数据类型时,serial_no 使用了类型H5T_NATIVE_INT,但在创建文件的数据类型时,serial_no 使用了H5T_STD_I64BE。他为什么要这样做?

    /*
 * Create the compound datatype for memory.
 */
memtype = H5Tcreate (H5T_COMPOUND, sizeof (sensor_t));
status = H5Tinsert (memtype, "Serial number",
            HOFFSET (sensor_t, serial_no), H5T_NATIVE_INT);
status = H5Tinsert (memtype, "Location", HOFFSET (sensor_t, location),
            strtype);
status = H5Tinsert (memtype, "Temperature (F)",
            HOFFSET (sensor_t, temperature), H5T_NATIVE_DOUBLE);
status = H5Tinsert (memtype, "Pressure (inHg)",
            HOFFSET (sensor_t, pressure), H5T_NATIVE_DOUBLE);

/*
 * Create the compound datatype for the file.  Because the standard
 * types we are using for the file may have different sizes than
 * the corresponding native types, we must manually calculate the
 * offset of each member.
 */
filetype = H5Tcreate (H5T_COMPOUND, 8 + sizeof (hvl_t) + 8 + 8);
status = H5Tinsert (filetype, "Serial number", 0, H5T_STD_I64BE);
status = H5Tinsert (filetype, "Location", 8, strtype);
status = H5Tinsert (filetype, "Temperature (F)", 8 + sizeof (hvl_t),
            H5T_IEEE_F64BE);
status = H5Tinsert (filetype, "Pressure (inHg)", 8 + sizeof (hvl_t) + 8,
            H5T_IEEE_F64BE);

/*
 * Create dataspace.  Setting maximum size to NULL sets the maximum
 * size to be the current size.
 */
space = H5Screate_simple (1, dims, NULL);

/*
 * Create the dataset and write the compound data to it.
 */
dset = H5Dcreate (file, DATASET, filetype, space, H5P_DEFAULT, H5P_DEFAULT,
            H5P_DEFAULT);
status = H5Dwrite (dset, memtype, H5S_ALL, H5S_ALL, H5P_DEFAULT, wdata);

这两种方法有什么区别?

【问题讨论】:

【参考方案1】:

来自http://www.hdfgroup.org/HDF5/doc/UG/UG_frame11Datatypes.html

H5T_NATIVE_INT 对应于 C int 类型。在基于 Intel 的 PC 上,此类型与 H5T_STD_I32LE 相同,而在 MIPS 系统上,这将等效于 H5T_STD_I32BE。

也就是说,H5T_NATIVE_INT 在不同类型的处理器上具有不同的内存布局。如果您的数据只在内存中使用,这意味着您的数据不会从这台机器中出去,您可能希望使用 H5T_NATIVE_INT 以获得更好的性能。

但是如果你的数据将被保存到文件中,并且将被不同的系统使用,你必须指定某种 int 类型来保持你的数据可以被正确读取,例如H5T_STD_I64BE 或 H5T_STD_I32LE。如果您使用 H5T_NATIVE_INT,并且您在基于 Intel 的 PC 上创建了一个数据文件,则该编号将保存为 H5T_STD_I32LE。当这个文件被 MIPS 系统使用时,它会读取到 H5T_STD_I32BE 的数字,这不是预期的。

【讨论】:

根据我的解释:文件类型为 NATIVE_some_type 是可以的;在回读内容时进行映射是客户的责任。换句话说:“当这个文件被 MIPS 系统使用时,它将读取的数字为 H5T_STD_I32BE,这不是预期的。”不是真的;客户端应该读回文件类型,并相应地创建内存布局。客户端应该期望字节顺序不匹配并通过适当的映射来缓解它。该示例演示了文件字节顺序/布局与主机(内存)字节顺序/布局解耦。 @StevenVarga 如果使用 H5T_NATIVE_INT,你不知道它是大端还是小端,除非你在某处放置一个标志来说明字节顺序是什么。即使您知道实际的字节顺序,在加载所有数据后转换它们也不是一件容易的事。而且代码维护也很困难。何必?保存到文件时为什么不使用明确的字节顺序?【参考方案2】:

这里的另一个答案是缺少一些关键思想,这使得使用 HDF5 数据类型看起来比实际更难。

首先,NATIVE 类型只是 C 类型在该平台上映射的别名(在构建 HDF5 库时会检测到这一点)。如果您在代码中使用它们并查看您使用 h5dump 工具创建的文件,您将不会看到 NATIVE 数据类型,而是会看到真正的数据类型(H5T_STD_I32LE 或诸如此类)。诚然,这些 NATIVE 类型有点令人困惑,但它们便于在 C 类型和 HDF5 数据类型之间进行映射,而无需知道您所在系统的字节顺序。

我想澄清的另一个误解是,库会在合理的情况下为您转换类型。如果数据集包含 H5T_STD_I32BE 值,并且您在 little-endian 系统上声明 I/O 缓冲区为 H5T_NATIVE_INT,则 HDF5 库将为您将 big-endian 数据集整数转换为内存中 little-endian 整数。您应该不需要自己执行字节交换。

这是一个简单的思考方式:

您在调用 H5Dcreate() 时声明了数据集的存储数据类型。 您在调用 H5Dread() 和 H5Dwrite() 时声明了I/O 缓冲区的数据类型

同样,如果这些不同并且类型转换是合理的,则数据将在读/写调用期间进行转换。

请注意,这种类型转换可能会对时间要求严格的应用程序产生性能影响。如果将写入和读取数据的平台在字节顺序或字长上不同,您可能需要显式设置数据类型而不是使用 NATIVE 别名,以便强制在不太重要的平台上进行转换。

示例:假设您有一个 BE 写入器和一个 LE 读取器,并且数据到达缓慢但读取必须尽可能快。在这种情况下,您需要显式创建数据集来存储 H5T_STD_I32LE 数据,以便在写入器上进行数据类型转换。

最后一件事——在构造复合类型时,最好使用 HOFFSET(s,m) 宏而不是手动计算偏移量。它更易于维护,您的代码会更好看。

如果您想了解有关 HDF5 数据类型的更多信息,请在此处查看用户指南的第 6 章: https://support.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide-Responsive%20HTML5/index.html

您还可以在此处查看参考手册中的 H5T API 文档: https://support.hdfgroup.org/HDF5/doc/RM/RM_H5Front.html

【讨论】:

以上是关于HDF5 复合类型 Native vs. IEEE的主要内容,如果未能解决你的问题,请参考以下文章

找不到合适的本地库。 native.libpath。* vs java.library.path

HDF5:复合数据类型,用于写入包含指向另一个结构的指针的结构

HDF5 中的嵌套复合数据类型

如何在 HDF5 C# 上创建复合数据集

是否可以从 Python 的 HDF5 文件中的复合数据集中读取字段名称?

HDF5Cpp 扩展复合数据集 Hyperslab 问题