我正在尝试做一些应该相当普遍的事情。将复合数据类型的数组写入hdf5文件,扩展文件并将数组的新值写出,依此类推。我想在一个循环中做这个。我将我的数据集初始化为零长度,然后根据需要在循环中扩展它。 如果循环是1次旅行,它可以正常工作:
HDF5 "mydata_1trip.h5" {
GROUP "/" {
DATASET "MYDATA" {
DATATYPE H5T_COMPOUND {
H5T_STD_I32LE "i4_name";
H5T_STD_I16LE "i21_name";
H5T_STD_I16LE "i22_name";
H5T_IEEE_F64LE "r8_name";
}
DATASPACE SIMPLE { ( 2 ) / ( H5S_UNLIMITED ) }
DATA {
(0): {
-100,
-1,
0,
1e+06
},
(1): {
-100,
-1,
0,
1e+06
} } } } }
使用2个循环循环,数据集正确扩展,但第二次写入 覆盖原始数据(并将垃圾放入第二个数据集)。所以问题似乎与偏移量有关吗?
HDF5 "mydata_2trip.h5" {
GROUP "/" {
DATASET "MYDATA" {
DATATYPE H5T_COMPOUND {
H5T_STD_I32LE "i4_name";
H5T_STD_I16LE "i21_name";
H5T_STD_I16LE "i22_name";
H5T_IEEE_F64LE "r8_name";
}
DATASPACE SIMPLE { ( 4 ) / ( H5S_UNLIMITED ) }
DATA {
(0): {
-200,
-2,
0,
2e+06
},
(1): {
-200,
-2,
0,
2e+06
},
(2): {
107382520,
1,
0,
0
},
(3): {
107375576,
1,
0,
4.94066e-324
}
}
}
}
}
这是代码
program read_test
USE hdf5
USE ISO_C_BINDING
implicit none
KIND参数
INTEGER, PARAMETER :: int_k1 = SELECTED_INT_KIND(1) ! This should map to INTEGER*1 on most modern processors
INTEGER, PARAMETER :: int_k2 = SELECTED_INT_KIND(4) ! This should map to INTEGER*2 on most modern processors
INTEGER, PARAMETER :: int_k4 = SELECTED_INT_KIND(8) ! This should map to INTEGER*4 on most modern processors
INTEGER, PARAMETER :: int_k8 = SELECTED_INT_KIND(16) ! This should map to INTEGER*8 on most modern processors
INTEGER, PARAMETER :: r_k4 = SELECTED_REAL_KIND(5) ! This should map to REAL*4 on most modern processors
INTEGER, PARAMETER :: r_k8 = SELECTED_REAL_KIND(10) ! This should map to REAL*8 on most modern processors
文件
CHARACTER(LEN=*), PARAMETER ::
& H5FILE_NAME="mydata.h5"
CHARACTER(LEN=*), PARAMETER :: DATASETNAME = "MYDATA"
type my_data
sequence
integer(kind=int_k4) :: i4
integer(kind=int_k2) :: i1_2,i2_2
real (kind=r_k8) :: r8
end type
integer(kind=int_k4) :: nsize=2,i
type(my_data),allocatable :: iblock(:)
INTEGER, PARAMETER :: RANK = 1
TYPE(my_data), pointer :: s1(:)
INTEGER(hid_t) :: s1_tid ! File datatype identifier
INTEGER(HID_T) :: file_id ! File identifier
INTEGER(HID_T) :: dset_id ! Dataset identifier
INTEGER(HID_T) :: dataspace ! Dataspace identifier
INTEGER(HID_T) :: memspace ! Memory dataspace identifier
INTEGER(HID_T) :: crp_list ! Dataset creation property identifier
INTEGER(hsize_t) :: DIMS(1) ! Dataspace dimensions
INTEGER(SIZE_T) :: type_size ! Size of the datatype
INTEGER(SIZE_T) :: compound_offset, sizeof_compound
INTEGER(HSIZE_T), DIMENSION(1) :: chunk_dims,size
INTEGER :: hdferr
TYPE(C_PTR) :: f_ptr
最大尺寸
INTEGER(HSIZE_T), DIMENSION(1) :: maxdims
INTEGER(HSIZE_T), DIMENSION(1) :: offset
INTEGER(HSIZE_T), DIMENSION(1) :: count
分配缓冲区:
allocate(iblock(nsize))
dims(1) = nsize
allocate(s1(dims(1)))
初始化FORTRAN接口。
CALL h5open_f(hdferr)
使用默认属性创建新文件。
CALL h5fcreate_f(h5file_name, H5F_ACC_TRUNC_F, file_id, hdferr)
我们最初将其设置为0.我们 可以在每个步骤扩展数据集。
maxdims = (/H5S_UNLIMITED_F/)
dims(1) = 0
write(*,*)" dims = ",dims
创建无限维度的数据空间。
CALL H5Screate_simple_f(RANK, dims, dataspace, hdferr,maxdims)
然后创建数据集创建属性列表。数据集的布局 使用无限尺寸时必须分块。的选择 块大小会影响性能,包括时间和磁盘空间。如果 块很小,你会有很多开销。如果它们是 太大了,您可能会分配不需要的空间和文件 可能最终会变得太大。这是一个玩具示例,所以我们会选择 一行的大块。
修改数据集创建属性,即启用分块
CALL h5pcreate_f(H5P_DATASET_CREATE_F, crp_list, hdferr)
chunk_dims(1) = nsize
CALL h5pset_chunk_f(crp_list, RANK, chunk_dims, hdferr)
创建内存数据类型。
CALL H5Tcreate_f(H5T_COMPOUND_F, H5OFFSETOF(C_LOC(s1(1)),
& C_LOC(s1(2))), s1_tid, hdferr)
CALL H5Tinsert_f(s1_tid, "i4_name",
& H5OFFSETOF(C_LOC(s1(1)),C_LOC(s1(1)%i4)),
& h5kind_to_type(int_k4,H5_INTEGER_KIND), hdferr)
CALL H5Tinsert_f(s1_tid, "i21_name",
& H5OFFSETOF(C_LOC(s1(1)),C_LOC(s1(1)%i1_2)),
& h5kind_to_type(int_k2,H5_INTEGER_KIND), hdferr)
CALL H5Tinsert_f(s1_tid, "i22_name",
& H5OFFSETOF(C_LOC(s1(1)),C_LOC(s1(1)%i2_2)),
& h5kind_to_type(int_k2,H5_INTEGER_KIND), hdferr)
CALL H5Tinsert_f(s1_tid, "r8_name",
& H5OFFSETOF(C_LOC(s1(1)),C_LOC(s1(1)%r8)),
& h5kind_to_type(r_k8,H5_REAL_KIND), hdferr)
创建数据集。
CALL H5Dcreate_f(file_id, datasetname, s1_tid, dataspace,
& dset_id, hdferr,crp_list)
关闭资源。现在创建了数据集,因此我们不需要 物业清单了。我们不再需要文件数据空间了,因为 当数据集将被扩展时,它将变为无效 仍然保持以前的程度。所以我们必须抓住更新的 无论如何都是文件数据空间。
call h5pclose_f(crp_list,hdferr)
CALL h5sclose_f(dataspace, hdferr)
我们创建一个内存数据空间来指示缓冲区的大小 记忆。
dims(1) = nsize
CALL h5screate_simple_f(RANK, dims, dataspace, hdferr)
设置输入数据
do i=1,2
iblock(:)%i4 = -100*i
iblock(:)%i1_2 = i
iblock(:)%i2_2 = -i
iblock(:)%r8 = 1.d6*i
将数据写入memtype
s1(:) = iblock(:)
我们创建一个内存数据空间来指示缓冲区的大小 记忆。 dims(1)已经是nsize
我们现在需要扩展数据集。我们设置了初始大小 数据集为0,因此我们需要首先扩展它。请注意,我们扩展 数据集本身,而不是数据空间。
size(1) = i*nsize
CALL h5dset_extent_f(dset_id, size, hdferr)
dims(1) = nsize
CALL h5screate_simple_f (rank, dims, memspace, hdferr)
CALL h5dget_space_f(dset_id, dataspace, hdferr)
offset(1) = (i-1)*nsize ! if this is in chunks
count(1) = nsize
CALL h5sselect_hyperslab_f(dataspace, H5S_SELECT_SET_F,
& offset, count, hdferr)
将数据数组写入数据集
f_ptr = C_LOC(s1(1))
CALL H5Dwrite_f(dset_id, s1_tid, f_ptr, hdferr)
CALL h5sclose_f(dataspace,hdferr)
enddo
发布资源
CALL H5Tclose_f(s1_tid, hdferr)
CALL h5sclose_f(memspace, hdferr)
CALL h5dclose_f(dset_id, hdferr)
CALL h5fclose_f(file_id, hdferr)
end program read_test