【问题标题】:Create hdf5 file from scratch using file image operations (memory mapped hdf5 files)使用文件映像操作从头开始创建 hdf5 文件(内存映射 hdf5 文件)
【发布时间】:2017-09-29 00:17:11
【问题描述】:

问题:我想使用内存映射的 HDF5 文件进行单元测试。是否可以从头开始创建它们?

状态:我已经阅读了 HDF5 文件图像操作document,并尝试应用它。根据使用的确切参数,我得到一个无效的文件标识符 (-1),或者随后创建数据集失败。

通常,我们的单元测试会编写新的测试文件,模仿用户将新创建的数据保存到磁盘上的文件。所以还没有一个现有的文件。在阅读 hdf5 文件映像操作的文档时,假设设置了初始文件映像。我没有任何 - 因为我试图通过我的测试尽可能接近实际用户场景。可以从空缓冲区创建这样的文件吗?

static const unsigned int FileSize = 1024 * 1024 * 100;
std::vector<unsigned char> buffer(FileSize, 0);     // initialize buffer with zeroes
int flags = H5LT_FILE_IMAGE_DONT_COPY | 
            H5LT_FILE_IMAGE_OPEN_RW | 
            H5LT_FILE_IMAGE_DONT_RELEASE;
m_file = H5LTopen_file_image(static_cast<void*>(buffer.data()), buffer.size(), flags);

如果想像示例中那样保留缓冲区的所有权,我没有得到有效的文件 ID。我怀疑 HDF5 中存在错误,但不幸的是留下了标志 H5LT_FILE_IMAGE_DONT_COPY | H5LT_FILE_IMAGE_DONT_RELEASE out 也没有用。

【问题讨论】:

    标签: hdf5


    【解决方案1】:

    根据@FreekNossin 的回答,这是一个更完整的代码,在可用的情况下使用 c++ API:

    #include<H5Cpp.h>
    
    /* create the HDF5 file image first */
    H5::FileAccPropList accPList=H5::FileAccPropList::DEFAULT;
    // https://confluence.hdfgroup.org/display/HDF5/H5P_SET_FAPL_CORE
    herr_t h5err=H5Pset_fapl_core(accPList.getId(),/* memory increment size: 4M */1<<22,/*backing_store*/false);
    if(h5err<0) throw std::runtime_error("H5P_set_fapl_core failed.");
    H5::H5File h5file("whatever",H5F_ACC_TRUNC,H5::FileCreatPropList::DEFAULT,accPList);
    
    /* add data like usual */
    H5::Group grp=h5file.createGroup("somegroup");
    /* ... */
    
    /* get the image */
    h5file.flush(H5F_SCOPE_LOCAL); // probably not necessary
    ssize_t imgSize=H5Fget_file_image(h5file.getId(),NULL,0); // first call to determine size
    std::vector<char> buf(imgSize);
    H5Fget_file_image(h5file.getId(),buf.data(),imgSize); // second call to actually copy the data into our buffer
    

    编辑: 代码中有一个陷阱:如果两个线程打开同一个"whatever" (presudo) 文件,则会抛出H5::FileIException: unable to truncate a file which is already open。我使用的一种解决方法是将堆栈(线程本地)变量的地址放入名称中:

    int _var=0;
    std::string hdf5name(("whatever+std::to_string((uintptr_t)&_var)).c_str());
    

    【讨论】:

    • 我想知道,是否有更可靠的方法来获取文件的线程安全唯一文件名?
    • 你到底是什么意思?据我所知,这个是完全可靠的;它只是不优雅。
    • 没有办法保证&amp;_var 不会返回相同的地址两次(从长远来看,比如几天),而 hdf 文件仍在使用中。
    • 是的。例如static int a=0;,然后使用a++构造伪文件名将是唯一的(除非你溢出int)。
    • 是的。然后static std::atomic&lt;int&gt; a=0;a++
    【解决方案2】:

    显然 H5LTOpen_file_image 封装了一些调用,这些调用也允许创建虚拟文件。这都是由核心文件驱动管理的。可以通过将一些参数传递给核心文件驱动程序来检索所需的结果。

    auto propertyList = H5Pcreate(H5P_FILE_ACCESS);
    auto h5Result = H5Pset_fapl_core(propertyList, m_buffer.GetSize(), false);
    assert(h5Result >= 0 && "H5Pset_fapl_core failed");
    m_file = H5Fcreate(name, flags, H5P_DEFAULT, propertyList);
    

    调用 H5Pset_fapl_core 的最后一个参数设置“虚拟后备存储”的布尔值。如果设置为 false,则文件内容不会写入磁盘。

    请注意,最后我必须使用开篇文章中提到的文档中的所有高级技巧才能真正让所有功能正常工作。该文档是一个很好的参考,但有些过时(枚举在最新版本中具有不同但相似的命名)。

    【讨论】:

      猜你喜欢
      • 2013-08-29
      • 1970-01-01
      • 2013-01-23
      • 1970-01-01
      • 2016-02-23
      • 2019-01-11
      • 2012-02-08
      • 1970-01-01
      • 2011-03-29
      相关资源
      最近更新 更多