在 Fortran 中读取 HDF5 数据集的子集时出现问题
Problems reading subset of HDF5 dataset in Fortran
我有一个非常大的 HDF5 文件,希望使用 FORTRAN 读取其中的一小部分。到目前为止,我的尝试都失败了,我对文档感到困惑。
如果您能给 FORTRAN 新手(但合理的 C/python 编码员)任何建议,我们将不胜感激。
特别是我很难理解数据space 和内存space 是什么,在我的代码中,根据我的文档,它们似乎没有按照我的预期进行读过。不过这可能是我自己的白痴!
这就是我正在尝试的:
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 补丁 1 进行编译
根据您对变量 dimsm
的描述和遗漏,我猜测您将该变量设置为您正在阅读的变量的完整维度。这些维度应该是您设置的 hyperslab 的维度,这也是您在 tmpdata
中保存读取结果的变量的维度。您可以使用与创建 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
.
我有一个非常大的 HDF5 文件,希望使用 FORTRAN 读取其中的一小部分。到目前为止,我的尝试都失败了,我对文档感到困惑。 如果您能给 FORTRAN 新手(但合理的 C/python 编码员)任何建议,我们将不胜感激。
特别是我很难理解数据space 和内存space 是什么,在我的代码中,根据我的文档,它们似乎没有按照我的预期进行读过。不过这可能是我自己的白痴!
这就是我正在尝试的:
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 补丁 1 进行编译根据您对变量 dimsm
的描述和遗漏,我猜测您将该变量设置为您正在阅读的变量的完整维度。这些维度应该是您设置的 hyperslab 的维度,这也是您在 tmpdata
中保存读取结果的变量的维度。您可以使用与创建 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
.