Skip to content

Commit 7d8e6c6

Browse files
committed
add rewrite char
ref: add char write
1 parent 291c55d commit 7d8e6c6

File tree

9 files changed

+248
-46
lines changed

9 files changed

+248
-46
lines changed

benchmark/CMakeLists.txt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,18 @@ project(h5mpi-benchmark
44
LANGUAGES C Fortran
55
)
66

7-
cmake_path(SET CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/Modules)
7+
cmake_path(SET CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/../cmake/Modules)
8+
9+
find_package(MPI COMPONENTS Fortran REQUIRED)
10+
find_package(HDF5 COMPONENTS parallel Fortran REQUIRED)
811

912
# --- auto-ignore build directory
1013
if(NOT EXISTS ${PROJECT_BINARY_DIR}/.gitignore)
1114
file(WRITE ${PROJECT_BINARY_DIR}/.gitignore "*")
1215
endif()
1316

17+
add_subdirectory(test)
18+
1419
set(runner_os \"${CMAKE_SYSTEM_NAME} ${CMAKE_SYSTEM_PROCESSOR}\")
1520
configure_file(perf.in.f90 perf.f90 @ONLY)
1621
add_library(perf OBJECT

reference/CMakeLists.txt

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,29 @@ project(ref
44
LANGUAGES C Fortran
55
)
66

7-
cmake_path(SET CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/Modules)
7+
enable_testing()
8+
9+
cmake_path(SET CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/../cmake/Modules)
10+
11+
find_package(MPI COMPONENTS Fortran REQUIRED)
12+
find_package(HDF5 COMPONENTS parallel Fortran REQUIRED)
813

914
# --- auto-ignore build directory
1015
if(NOT EXISTS ${PROJECT_BINARY_DIR}/.gitignore)
1116
file(WRITE ${PROJECT_BINARY_DIR}/.gitignore "*")
1217
endif()
1318

19+
add_executable(write_char write_char.f90)
20+
target_link_libraries(write_char PRIVATE HDF5::HDF5 MPI::MPI_Fortran)
21+
add_test(NAME WriteChar
22+
COMMAND ${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} 2 $<TARGET_FILE:write_char>
23+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
24+
)
25+
1426
# old standalone example, not useful for production.
15-
add_executable(simple simple.f90)
16-
target_link_libraries(simple PRIVATE HDF5::HDF5 MPI::MPI_Fortran)
27+
add_executable(write_coll write_collective.f90)
28+
target_link_libraries(write_coll PRIVATE HDF5::HDF5 MPI::MPI_Fortran)
29+
add_test(NAME WriteCollective
30+
COMMAND ${MPIEXEC_EXECUTABLE} ${MPIEXEC_NUMPROC_FLAG} 2 $<TARGET_FILE:write_coll>
31+
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
32+
)

reference/write_char.f90

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
module proto
2+
3+
use mpi, only : MPI_INFO_NULL, MPI_COMM_WORLD
4+
use hdf5
5+
6+
implicit none (type, external)
7+
8+
private
9+
public :: create_file, create_dataset, write_dataset
10+
11+
contains
12+
13+
subroutine create_file(fn, file_id)
14+
15+
character(*), intent(in) :: fn
16+
integer(HID_T), intent(out) :: file_id
17+
18+
integer(HID_T) :: fapl
19+
integer :: ierr
20+
21+
! collective: setup for MPI access
22+
call h5pcreate_f(H5P_FILE_ACCESS_F, fapl, ierr)
23+
call h5pset_fapl_mpio_f(fapl, MPI_COMM_WORLD, MPI_INFO_NULL, ierr)
24+
25+
! collective: create file
26+
call h5fcreate_f(fn, H5F_ACC_TRUNC_F, file_id, ierr, access_prp = fapl)
27+
if(ierr/=0) error stop "h5fcreate"
28+
call h5pclose_f(fapl, ierr)
29+
if(ierr/=0) error stop "h5pclose"
30+
31+
end subroutine create_file
32+
33+
34+
subroutine create_dataset(dset_name, file_id, dtype, dset_id, filespace, type_id, charlen)
35+
36+
character(*), intent(in) :: dset_name
37+
integer(HID_T), intent(in) :: file_id, dtype
38+
integer(HID_T), intent(out) :: dset_id, filespace
39+
integer(HID_T), optional, intent(out) :: type_id
40+
integer, optional, intent(in) :: charlen
41+
42+
integer :: ierr
43+
integer(HID_T) :: dcpl
44+
45+
dcpl = H5P_DEFAULT_F
46+
47+
call h5screate_f(H5S_SCALAR_F, filespace, ierr)
48+
if(ierr/=0) error stop "h5screate"
49+
50+
if(dtype == H5T_NATIVE_CHARACTER) then
51+
if(.not.present(charlen)) error stop "character needs charlen"
52+
if(.not.present(type_id)) error stop "character needs type_id"
53+
! define character
54+
CALL h5tcopy_f(H5T_NATIVE_CHARACTER, type_id, ierr)
55+
if(ierr/=0) error stop "h5tcopy"
56+
CALL h5tset_size_f(type_id, int(charlen, SIZE_T), ierr)
57+
if(ierr/=0) error stop "h5tset_size"
58+
else
59+
type_id = dtype
60+
endif
61+
62+
! collective: create dataset
63+
call h5dcreate_f(file_id, dset_name, type_id, filespace, dset_id, ierr, dcpl_id=dcpl)
64+
if(ierr/=0) error stop "h5dcreate"
65+
66+
call h5pclose_f(dcpl, ierr)
67+
if (ierr /= 0) error stop "h5pclose"
68+
69+
end subroutine create_dataset
70+
71+
72+
subroutine write_dataset(dset_id, type_id, data, dset_dims)
73+
74+
integer(HID_T), intent(in) :: dset_id, type_id
75+
class(*), intent(in) :: data
76+
integer(HSIZE_T), intent(in) :: dset_dims(:)
77+
78+
integer(HID_T) :: dxpl
79+
integer :: ierr
80+
81+
! Create property list for collective dataset write
82+
call h5pcreate_f(H5P_DATASET_XFER_F, dxpl, ierr)
83+
if (ierr/=0) error stop "h5pcreate"
84+
call h5pset_dxpl_mpio_f(dxpl, H5FD_MPIO_COLLECTIVE_F, ierr)
85+
if (ierr/=0) error stop "h5pset_dxpl"
86+
87+
! For independent write use
88+
! call h5pset_dxpl_mpio_f(dcpl, H5FD_MPIO_INDEPENDENT_F, ierr)
89+
90+
! collective: Write dataset
91+
select type(data)
92+
type is (character(*))
93+
call h5dwrite_f(dset_id, type_id, data, dset_dims, ierr, xfer_prp = dxpl)
94+
class default
95+
error stop "write_dataset: unhandled type"
96+
end select
97+
if (ierr/=0) error stop "h5dwrite"
98+
99+
100+
call h5tclose_f(type_id, ierr)
101+
if(ierr/=0) error stop "h5tclose"
102+
call h5pclose_f(dxpl, ierr)
103+
if (ierr/=0) error stop "h5pclose"
104+
call h5dclose_f(dset_id, ierr)
105+
if (ierr/=0) error stop "h5dclose"
106+
107+
end subroutine write_dataset
108+
109+
end module proto
110+
111+
112+
program simple
113+
!! this example has undesirable effect that all workers must have copy of data.
114+
!! we "broadcast" our simulated data here implicitly
115+
!! a more optimal case is to use hyperslabs with each worker
116+
117+
use mpi, only : mpi_init
118+
use hdf5
119+
use proto
120+
121+
implicit none (type, external)
122+
123+
external :: mpi_finalize
124+
125+
character(:), allocatable :: fn
126+
127+
integer(HID_T) :: file_id, dset_id, filespace, dcpl, type_id
128+
129+
character(:), allocatable :: c1, c2
130+
131+
integer(HSIZE_T) :: dset_dims(0)
132+
133+
integer :: ierr, i, j, k
134+
135+
call mpi_init(ierr)
136+
137+
fn = "char.h5"
138+
c1 = "42"
139+
c2 = "this is a Little string!"
140+
141+
call h5open_f(ierr)
142+
if(ierr/=0) error stop "h5open"
143+
144+
call create_file(fn, file_id)
145+
146+
call create_dataset("/c1", file_id, H5T_NATIVE_CHARACTER, dset_id, filespace, type_id, len(c1))
147+
call write_dataset(dset_id, type_id, c1, dset_dims)
148+
149+
call create_dataset("/c2", file_id, H5T_NATIVE_CHARACTER, dset_id, filespace, type_id, len(c2))
150+
call write_dataset(dset_id, type_id, c2, dset_dims)
151+
152+
! wind down
153+
call h5sclose_f(filespace, ierr)
154+
if (ierr/=0) error stop "h5sclose"
155+
call h5fclose_f(file_id, ierr)
156+
if (ierr/=0) error stop "h5fclose"
157+
call h5close_f(ierr)
158+
if (ierr/=0) error stop "h5close"
159+
160+
call mpi_finalize(ierr)
161+
if (ierr/=0) error stop "mpi_finalize"
162+
163+
print *,"OK: write collective"
164+
165+
end program

reference/simple.f90 renamed to reference/write_collective.f90

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,5 +80,8 @@ program simple
8080
call h5close_f(ierr)
8181

8282
call mpi_finalize(ierr)
83+
if (ierr/=0) error stop "mpi_finalize"
84+
85+
print *,"OK: write collective"
8386

8487
end program

src/interface.f90

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -413,21 +413,26 @@ subroutine ph5open(self, filename, action, mpi, comp_lvl, shuffle, fletcher32, d
413413
integer :: ierr
414414
integer(HID_T) :: fapl !< file access property list
415415

416+
if(self%is_open()) then
417+
write(stderr,*) 'h5fortran:open: file handle already open: '//self%filename
418+
return
419+
endif
420+
416421
laction = "rw"
417422
if (present(action)) laction = action
418423

419424
self%use_mpi = mpi
420425

421426
if(self%use_mpi) then
422-
call mpi_comm_rank(MPI_COMM_WORLD, self%mpi_id, ierr)
427+
call mpi_comm_rank(mpi_h5comm, self%mpi_id, ierr)
423428
if(ierr /= 0) error stop "ERROR:h5fortran:open: could not get MPI ID"
424429
endif
425430

426431
if(present(debug)) self%debug = debug
427432

428433
call get_hdf5_config(self%parallel_compression)
429434
if(self%use_mpi .and. .not. self%parallel_compression .and. self%comp_lvl > 0) then
430-
write(stderr, '(a)') "h5fortran:open: parallel compression is NOT available"
435+
write(stderr, '(a)') "WARNING:h5fortran:open: parallel compression is NOT available"
431436
!! don't set to 0 because non-MPI writes can compress.
432437
!! We warn again and disable compression for each attempted MPI compress write.
433438
endif
@@ -443,34 +448,34 @@ subroutine ph5open(self, filename, action, mpi, comp_lvl, shuffle, fletcher32, d
443448
if(present(fletcher32)) self%fletcher32 = fletcher32
444449

445450
if(self%comp_lvl < 0) then
446-
write(stderr, '(a)') "h5fortran:open: compression level must be >= 0, setting comp_lvl = 0"
451+
write(stderr, '(a)') "ERROR:h5fortran:open: compression level must be >= 0, setting comp_lvl = 0"
447452
self%comp_lvl = 0
448453
elseif(self%comp_lvl > 9) then
449-
write(stderr, '(a)') "h5fortran:open: compression level must be <= 9, setting comp_lvl = 9"
454+
write(stderr, '(a)') "ERROR:h5fortran:open: compression level must be <= 9, setting comp_lvl = 9"
450455
self%comp_lvl = 9
451456
endif
452457

453458
call h5open_f(ierr)
454-
if(ierr/=0) error stop "h5open: could not open HDF5 library"
459+
if(ierr/=0) error stop "ERROR:h5fortran:h5open: could not open HDF5 library"
455460
!! OK to call repeatedly
456461
!! https://support.hdfgroup.org/HDF5/doc/RM/RM_H5.html#Library-Open
457462

458463
if(self%use_mpi) then
459464
!! collective: setup for MPI access
460465
call h5pcreate_f(H5P_FILE_ACCESS_F, fapl, ierr)
461-
if(ierr/=0) error stop "h5open:h5pcreate could not collective open property"
466+
if(ierr/=0) error stop "ERROR:h5fortran:open:h5pcreate could not collective open property for " // filename
462467
call h5pset_fapl_mpio_f(fapl, mpi_h5comm, mpi_h5info, ierr)
463-
if(ierr/=0) error stop "h5open:h5pset_fapl_mpio could not collective open file"
468+
if(ierr/=0) error stop "ERROR:h5fortran:open:h5pset_fapl_mpio could not collective open file for " // filename
464469
else
465470
fapl = H5P_DEFAULT_F
466471
endif
467472

468473
select case(laction)
469474
case('r')
470-
if(.not. is_hdf5(filename)) error stop "h5fortran:open: file does not exist: "//filename
475+
if(.not. is_hdf5(filename)) error stop "ERROR:h5fortran:open: file does not exist: "//filename
471476
call h5fopen_f(filename, H5F_ACC_RDONLY_F, self%file_id, ierr, access_prp=fapl)
472477
case('r+')
473-
if(.not. is_hdf5(filename)) error stop "h5fortran:open: file does not exist: "//filename
478+
if(.not. is_hdf5(filename)) error stop "ERROR:h5fortran:open: file does not exist: "//filename
474479
call h5fopen_f(filename, H5F_ACC_RDWR_F, self%file_id, ierr, access_prp=fapl)
475480
case('rw', 'a')
476481
if(is_hdf5(filename)) then
@@ -481,14 +486,14 @@ subroutine ph5open(self, filename, action, mpi, comp_lvl, shuffle, fletcher32, d
481486
case ('w')
482487
call h5fcreate_f(filename, H5F_ACC_TRUNC_F, self%file_id, ierr, access_prp=fapl)
483488
case default
484-
error stop 'h5fortran:open Unsupported action= ' // laction
489+
error stop 'ERROR:h5fortran:open Unsupported action ' // laction // ' for ' // filename
485490
end select
486491

487-
if(ierr/=0) error stop "h5open/create: could not initialize HDF5 file: " // filename // " action: " // laction
492+
if(ierr/=0) error stop "ERROR:h5open/create: could not initialize HDF5 file: " // filename // " action: " // laction
488493

489494
if(fapl /= H5P_DEFAULT_F) then
490495
call h5pclose_f(fapl, ierr)
491-
if(ierr/=0) error stop "h5mpi:open:h5pclose: " // filename
496+
if(ierr/=0) error stop "ERROR:h5fortran:open:h5pclose: " // filename
492497
endif
493498

494499
self%filename = filename
@@ -582,7 +587,7 @@ logical function is_open(self)
582587
integer :: ierr
583588

584589
call h5iis_valid_f(self%file_id, is_open, ierr)
585-
if(ierr /= 0) error stop "h5fortran:is_open:h5iis_valid: " // self%filename
590+
if(ierr /= 0) error stop "ERROR:h5fortran:is_open:h5iis_valid: " // self%filename
586591

587592
! call h5iget_type_f(self%file_id, hid_type, ierr)
588593
! if(ierr /= 0 .or. hid_type /= H5I_FILE_F) is_open = .false.

0 commit comments

Comments
 (0)