在 Fortran 中读取 HDF5 数据集的子集时出现问题

Posted

技术标签:

【中文标题】在 Fortran 中读取 HDF5 数据集的子集时出现问题【英文标题】:Problems reading subset of HDF5 dataset in Fortran 【发布时间】:2016-01-24 06:06:49 【问题描述】:

我有一个非常大的 HDF5 文件,并希望使用 FORTRAN 读取其中的一小部分。到目前为止,我的尝试都失败了,我对文档感到困惑。 您可以给 FORTRAN 新手(但合理的 C/python 编码器)的任何指针将不胜感激。

特别是我很难理解数据空间和内存空间是什么,在我的代码中,根据我阅读的文档,它们似乎没有按照我的预期做。不过,这可能是我自己的白痴!

这就是我正在尝试的:

integer, allocatable                    :: tmpdata(:,:) ! Array to contain data subset
integer(HID_T)                          :: fid          ! HDF5 File ID
integer(HID_T)                          :: did          ! Dataset ID
integer                                 :: error        ! Error variable
integer(HSIZE_T), dimension(1:2)        :: count        ! Number of px to read (x,y)
integer(HSIZE_T), dimension(1:2)        :: offset       ! Starting point for read (x,y)
integer(HID_T)                          :: dataspace        ! Dataspace
integer(HID_T)                          :: memspace     ! Memoryspace

offset=(/58000,22000/)          ! Set offset in 2d dataset
count=(/1200,1200/)             ! Set # pixels to read (1200x1200 slab)
allocate(tmpdata(1200,1200))        ! Allocate space to store this slab

call h5open_f(error)
call h5fopen_f ("myfile.h5", H5F_ACC_RDWR_F, fid, error)        ! Open HDF5 file

call h5dopen_f(fid, "mydataset", did, error)        ! Open dataset
call h5dget_space_f(did, dataspace, error)          ! Retrieve dataspace 


call h5screate_simple_f(2, count, memspace, error)      !Create memspace, rank=2,size=1200x1200 
call h5sselect_hyperslab_f(dataspace, H5S_SELECT_SET_F, offset, count, error)       ! Select slab in the data 
call h5dread_f(did, H5T_NATIVE_INTEGER, tmpdata, dimsm, error,memspace,dataspace)       ! Read the data from the HDF5 file into the tmpdata array

! Close everything
-snip-

在调用 h5dread_f 之前一切正常。然后我得到一个段错误。如果我将 tmpdata 设置为等于 HDF5 文件中实际数据集的大小,那么它可以工作,但这不是一个好的解决方案,因为对于某些文件,数据集太大而无法存储在内存中。 有任何想法吗?希望我只是在做一些愚蠢的事情。如果这很重要,我将在 Ubuntu 14.04 上使用 ifort 和 HDF5-1.8.15 Patch 1 进行编译

【问题讨论】:

dimsm 是如何声明的? dimsminteger(HSIZE_T) :: dimsm(2) 的值 [1200, 1200] ? 【参考方案1】:

根据您对变量dimsm 的描述和省略,我猜您已将该变量设置为您正在阅读的变量的完整维度。这些尺寸应该是您设置的 hyperslab 的尺寸,这也是您在tmpdata 中保存读取结果的变量的尺寸。您可以在 read 调用中使用与创建 hyperslab 相同的数组 count

变化:

call h5dread_f(did, H5T_NATIVE_INTEGER, tmpdata, dimsm, error,memspace,dataspace)       

call h5dread_f(did, H5T_NATIVE_INTEGER, tmpdata, count, error,memspace,dataspace)    

你的阅读应该可以工作。

发生的事情(如果我的假设是正确的)是 dimsm 包含完整数据集维度的值(或两个维度中大于 1200 的任何值),因此读取数据的调用尝试读取外部数据数据空间的边界(在给定的偏移量处设置为 1200x1200 视图),如果这不是段错误,那么它将尝试将大于 1200x1200 的读取放入 1200x1200 变量tmpdata

【讨论】:

抱歉延迟回复 - 我前一阵子修复了这个问题,忘记了我在这里发帖。对于偶然发现此主题的其他任何人-此答案是正确的。它会解决我讨论的问题。 @os1 你能告诉我你使用的 hdf5 版本吗?我可以在 hdf5-1.10.x 源代码中看到这个子例程被注释掉了。在我的应用程序中出现以下错误时询问-“此通用子例程调用没有匹配的特定子例程。[H5DREAD_F]” @PuneetS.Chauhan 你在看什么版本? h5dread_f 是一些模块过程的接口,在 HDF5 1.10 中的文件 fortran/src/H5DFF.F90 中定义,在 HDF5 1.8 中可能位于类似位置。你的模块中是否有 use hdf5 来获取所有 hdf5 代码? @puneets.chauhan 也是,该错误表明正在找到h5dread_f,但您使用的参数与通用接口列出的任何可能的子例程都不匹配。 Doie 检查你的论点的数量和类型。 @casey,我在 hdf5 论坛上提出了这个问题,并提供了更多细节。请看一下 - forum.hdfgroup.org/t/….

以上是关于在 Fortran 中读取 HDF5 数据集的子集时出现问题的主要内容,如果未能解决你的问题,请参考以下文章

HDF5 用于使用 fortran 编写的数据文件

在 fortran 中将写入附加到 hdf5 文件

致命错误:在 (1) 处打开的文件“hdf5.mod”不是 GNU Fortran 模块文件

从 Fortran 中的 HDF 文件中读取长度未知的数组

如何从 C++ 中的 hdf5 文件中读取数据块?

如何使用 Fortran API 将字符串数组写入 HDF5 数据集?