HDF5复合类型Native与IEEE

时间:2013-02-28 21:32:29

标签: c++ c hdf5 dataformat

我只是拿起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);

这两种方法有什么区别?

2 个答案:

答案 0 :(得分:5)

来自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,这是不期望的。

答案 1 :(得分:0)

这里的另一个答案是缺少一些关键想法,并且使用HDF5数据类型似乎比它更难。

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

我想澄清的另一个误解是,在合理的情况下,库会为你转换类型。如果数据集包含H5T_STD_I32BE值并且您在小端系统上将I / O缓冲区声明为H5T_NATIVE_INT,则HDF5库会将big-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