HDF5中的嵌套复合数据类型

时间:2013-11-20 14:28:13

标签: c++ c hdf5

我是一个从事C ++应用程序的团队的一员,该应用程序处理各种类型的消息并以各种格式输出它们。出于本讨论的目的,可以将消息视为名称 - 值对的集合。值通常是数字,但可以是字符串。消息的结构基本上是在处理时发现的。 消息可以任意大,因此不允许在内存中存储表示。消息一次处理一个名称 - 值对。消息可以具有内部结构,由名称 - 值对中的名称捕获。一个很好的比喻是考虑目录层次结构中的文件名。

我正在开发一个处理这些消息的子系统,并使用低级HDF5 API生成HDF输出。由于我在上面描述的约束,我使用的方法涉及对消息的两次传递。在第一遍中,我收集布局信息并构建复合数据类型和数据集。然后我对消息进行第二次传递以写出值。因为我一次写一个值,所以我有一个这样的序列:


 // name, value, dataType, dtSize, ctDataSet and ctSpace have been defined elsewhere 
hid_t valueDT = H5Tcreate(H5T_COMPOUND, dtSize);
herr_t status = H5Tinsert(valueDT, name, 0, dataType);
hid_t filespace = H5Dget_space(ctDataSet);
hsize_t offset[] = { 0 };
hsize_t dim[] = [ 1 };
status = H5Sselect_hyperslab(filespace, H5S_SELECT_SET, offset, NULL,
                                             dim, NULL);
status = H5Dwrite(ctDataSet, valueDT, ctSpace, filespace, H5P_DEFAULT, &value);

我有这个工作,我现在正在尝试扩展它来处理嵌套的复合数据类型。我已经获得了第一次传球,但我仍然坚持第二次传球。代码段中的代码构建与值关联的独立数据类型,为其指定与数据集中已存在的字段对应的名称,然后同步HDF5以将值作为数据集的一部分写出。 我意识到我并没有明确指出使用的名称。假设我们在位置中查看字段 x 。使用的名称为 position.x

当这个值属于内部复合数据类型时,我很困惑如何建立关联。任何见解都会感激不尽。

2 个答案:

答案 0 :(得分:0)

您需要在每个嵌套级别创建正确的HDF5数据类型,从底部开始。然后,一旦您可以使用total compound datatype创建数据集,然后继续将数据写入文件。

我刚刚完成了这样的事情,除了我在Common Lisp中使用HDF5。我最终做的是定义一个类型规范(听起来像你的消息)来完全描述数据类型的结构,然后使用memoization(用于记忆函数输出的花哨字)生成C结构。

作为示例:假设您具有以下结构(在伪代码中):

Type = {
    x of Xtype;
    y of Ytype;
}

您可以通过执行

为Type创建复合数据类型
  1. 为Xtype创建HDF5数据类型(这是递归的,应该被记忆)
  2. 为Ytype创建HDF5数据类型(就像这样)
  3. 使用Xtype和Ytype的HDF5数据类型为Type创建HDF5数据类型。
  4. 这确实要求在第一次传递期间你已经完全确定了数据类型的结构,但这听起来不像你正在做的那样。

    要扩展示例,您需要做的是

    1. 获取复合结构的数据类型规范列表。
    2. (递归)为每个类型规范生成HDF5数据类型
    3. 从生成的HDF5数据类型中组装总HDF5复合类型。
    4. 将数据填入(递归)复合结构

      通常有两种方法。

      源代码生成

      您可以在第一次传递数据时创建用于访问/填充结构的代码。如果您想编写了解C / C ++结构和类的代码,因为数据类型是静态的,那么这是必要的,因此如果在编译时类型不存在,那么它在运行时就不能存在。因此,在编译期间通过生成C ++代码使类型存在,然后编译然后作为第二遍运行。

      这种方法对你所做的事情听起来并不太有希望,因为它听起来你会处理一个相当大的消息流,这需要相当多的代码生成和编译。那么,接下来的方法:

      原始二进制数据访问

      这种方法完全不使用静态类型的结构,这消除了生成C / C ++复合类型的要求。

      您所做的是使用您所掌握的有关数据类型的信息来计算复合数据类型的总大小以及类型成员在内存块中出现的总类型的偏移量。这可以像HDF5类型生成一样递归地完成。

      示例:如果您有复合类型

      Type = {
          x of Xtype;
          y of Ytype;
      }
      

      你会

      1. 通过以递归方式递减到Type的结构中获取Type的总大小,将XtypeYtype的大小相加,这些大小通过以相同方式下降到其结构中而找到

      2. 在内存中分配Type个字节的大小。

      3. 获取构成Type对象的所有基本结构元素的偏移量。因此,如果Xtype是复合的,那么你必须得到Xtype的成员,如果其中任何一个是复合的,你会得到它的成员等。

      4. 将每个基本结构元素写入适当偏移量的已分配内存中。这必须以递归方式完成,因为XtypeYtype可能是复合类型。

      5. 这种方法有效,因为数据是(至少从程序员的角度来看)连续分配的,因此xy并排放置在已分配的内存中。

        在这种方法中,您不得不放弃使用结构/类的便利,但这就是编译器在幕后管理结构/类的方式。

答案 1 :(得分:0)

我最终尝试了一种与我最初描述的方法截然不同的方法。我创建了一个数据集,而不是尝试将消息映射到复合数据类型,而是为消息中的每个字段创建一个数据集 >。当我处理消息的后续实例时,我更改了每个数据集的范围。在消息字段是可选的情况下,我在数据集上设置了一个属性,以确定哪些消息实例具有与之关联的值。

令我惊讶的是,在给定相同输入的情况下,“许多数据集”方法会产生比“复合数据集”方法更大的输出文件。我天真的期望是它会更小 - 但如果使用我错过的API有微妙之处,我也不会感到惊讶。然而,有一个更棘手的问题。输出文件的使用者将使用 MATLAB 来读取它们。 MATLAB 确实有一些高级函数来读取 HDF5 文件 - 特别是 h5read ()。当 h5read ()实现时,其参数之一是您要提取的数据集的名称。我真的不想要求用户单独提取他们可能感兴趣的每个数据集。任何人都可以想到在数据集中包装顶级的合理方法吗?