48 use hdf5_session,
only: hdf5_session_init, hdf5_session_finalize
49 use num_types,
only: dp, sp
50 use mpi_f08,
only: mpi_allreduce, mpi_scan, mpi_in_place, mpi_info_null, &
51 mpi_integer, mpi_sum, mpi_max
52 use comm,
only: neko_comm, pe_rank, pe_size
53 use device,
only: device_to_host, host_to_device
58 character(len=*),
parameter :: SD_GROUP =
'/SteepestDescent/checkpoint'
68 module subroutine sd_optimizer_save_checkpoint_hdf5(object, filename, &
70 class(steepest_descent_optimizer_t),
intent(inout) :: object
71 character(len=*),
intent(in) :: filename
72 logical,
intent(in),
optional :: overwrite
73 integer(hid_t) :: fapl_id, file_id, sd_grp_id, grp_id, filespace, attr_id
74 integer(hsize_t) :: ddim(1)
75 integer :: ierr, info, n, n_global, n_accum, n_array(pe_size)
76 logical :: overwrite_flag, link_exists
78 overwrite_flag = .false.
79 if (
present(overwrite)) overwrite_flag = overwrite
82 call object%xold1%copy_from(device_to_host, .true.)
83 call object%xold2%copy_from(device_to_host, .true.)
84 call object%delta%copy_from(device_to_host, .true.)
87 n = object%xold1%size()
89 n_array(pe_rank + 1) = n
90 call mpi_allreduce(mpi_in_place, n_array, pe_size, mpi_integer, mpi_sum, &
92 n_global = sum(n_array)
93 call mpi_scan(n, n_accum, 1, mpi_integer, mpi_sum, neko_comm, ierr)
98 call hdf5_session_init()
99 call h5pcreate_f(h5p_file_access_f, fapl_id, ierr)
100 info = mpi_info_null%mpi_val
101 call h5pset_fapl_mpio_f(fapl_id, neko_comm%mpi_val, info, ierr)
103 call h5fopen_f(trim(filename), h5f_acc_rdwr_f, file_id, ierr, &
104 access_prp = fapl_id)
105 if (ierr .ne. 0)
then
106 call neko_error(
'steepest_descent: unable to open HDF5 file "' // &
107 trim(filename) //
'"')
110 link_exists = .false.
111 call h5lexists_f(file_id,
'SteepestDescent', link_exists, ierr)
112 if (link_exists)
then
113 call h5gopen_f(file_id,
'SteepestDescent', sd_grp_id, ierr)
115 call h5gcreate_f(file_id,
'SteepestDescent', sd_grp_id, ierr)
118 link_exists = .false.
119 call h5lexists_f(sd_grp_id,
'checkpoint', link_exists, ierr)
120 if (link_exists)
then
121 if (.not. overwrite_flag)
then
122 call neko_error(
'steepest_descent: HDF5 file "' // &
123 trim(filename) //
'" already contains a steepest descent ' // &
124 'checkpoint; use overwrite option to replace')
126 call h5ldelete_f(sd_grp_id,
'checkpoint', ierr)
128 call h5gcreate_f(sd_grp_id,
'checkpoint', grp_id, ierr)
129 call h5gclose_f(sd_grp_id, ierr)
135 call h5screate_f(h5s_scalar_f, filespace, ierr)
136 call h5acreate_f(grp_id,
'n_global', h5t_native_integer, filespace, &
137 attr_id, ierr, h5p_default_f, h5p_default_f)
138 call h5awrite_f(attr_id, h5t_native_integer, n_global, ddim, ierr)
139 call h5aclose_f(attr_id, ierr)
140 call h5sclose_f(filespace, ierr)
142 ddim(1) = int(pe_size, hsize_t)
143 call h5screate_simple_f(1, ddim, filespace, ierr)
144 call h5acreate_f(grp_id,
'n', h5t_native_integer, filespace, attr_id, &
146 call h5awrite_f(attr_id, h5t_native_integer, n_array, ddim, ierr)
147 call h5aclose_f(attr_id, ierr)
148 call h5sclose_f(filespace, ierr)
153 call sd_write_dist(grp_id,
'xold1', object%xold1, n_accum - n, n_global)
154 call sd_write_dist(grp_id,
'xold2', object%xold2, n_accum - n, n_global)
155 call sd_write_dist(grp_id,
'delta', object%delta, n_accum - n, n_global)
160 call h5gclose_f(grp_id, ierr)
161 call h5fclose_f(file_id, ierr)
162 call h5pclose_f(fapl_id, ierr)
163 call hdf5_session_finalize()
165 end subroutine sd_optimizer_save_checkpoint_hdf5
171 module subroutine sd_optimizer_load_checkpoint_hdf5(object, filename)
172 class(steepest_descent_optimizer_t),
intent(inout) :: object
173 character(len=*),
intent(in) :: filename
174 integer(hid_t) :: fapl_id, file_id, grp_id, attr_id, space_id
175 integer(hsize_t) :: ddim(1), n_stored
176 integer :: ierr, info, n, n_global, n_accum, n_array(pe_size)
177 integer :: n_global_file, mismatch
180 n = object%xold1%size()
181 call mpi_allreduce(n, n_global, 1, mpi_integer, mpi_sum, neko_comm, ierr)
182 call mpi_scan(n, n_accum, 1, mpi_integer, mpi_sum, neko_comm, ierr)
187 call hdf5_session_init()
188 call h5pcreate_f(h5p_file_access_f, fapl_id, ierr)
189 info = mpi_info_null%mpi_val
190 call h5pset_fapl_mpio_f(fapl_id, neko_comm%mpi_val, info, ierr)
191 call h5fopen_f(trim(filename), h5f_acc_rdonly_f, file_id, ierr, &
192 access_prp = fapl_id)
193 call h5gopen_f(file_id, sd_group, grp_id, ierr)
195 if (ierr .ne. 0)
then
196 call neko_error(
'steepest_descent: unable to open HDF5 file "' // &
197 trim(filename) //
'" or group "' // sd_group //
'"')
205 call h5aopen_f(grp_id,
'n_global', attr_id, ierr)
206 call h5aread_f(attr_id, h5t_native_integer, n_global_file, ddim, ierr)
207 call h5aclose_f(attr_id, ierr)
210 call h5aopen_f(grp_id,
'n', attr_id, ierr)
211 call h5aget_space_f(attr_id, space_id, ierr)
212 call h5sget_simple_extent_npoints_f(space_id, n_stored, ierr)
213 call h5sclose_f(space_id, ierr)
214 if (n_stored .ne. int(pe_size, hsize_t))
then
215 call neko_error(
'steepest_descent: checkpoint was written with a ' // &
216 'different number of ranks')
220 ddim(1) = int(pe_size, hsize_t)
221 call h5aread_f(attr_id, h5t_native_integer, n_array, ddim, ierr)
222 call h5aclose_f(attr_id, ierr)
224 if (n_global_file .ne. n_global)
then
225 call neko_error(
'steepest_descent: mismatch in n_global during ' // &
232 if (n_array(pe_rank + 1) .ne. n) mismatch = 1
233 call mpi_allreduce(mpi_in_place, mismatch, 1, mpi_integer, mpi_max, &
235 if (mismatch .ne. 0)
then
236 call neko_error(
'steepest_descent: mismatch in n during HDF5 read')
242 call sd_read_dist(grp_id,
'xold1', object%xold1, n_accum - n, n_global)
243 call sd_read_dist(grp_id,
'xold2', object%xold2, n_accum - n, n_global)
244 call sd_read_dist(grp_id,
'delta', object%delta, n_accum - n, n_global)
249 call h5gclose_f(grp_id, ierr)
250 call h5fclose_f(file_id, ierr)
251 call h5pclose_f(fapl_id, ierr)
252 call hdf5_session_finalize()
255 call object%xold1%copy_from(host_to_device, .true.)
256 call object%xold2%copy_from(host_to_device, .true.)
257 call object%delta%copy_from(host_to_device, .true.)
259 end subroutine sd_optimizer_load_checkpoint_hdf5
266 function sd_h5t_real()
result(h5t_real)
267 integer(hid_t) :: h5t_real
271 h5t_real = h5t_native_double
273 h5t_real = h5t_native_real
275 call neko_error(
'steepest_descent: unsupported real kind for HDF5')
278 end function sd_h5t_real
289 subroutine sd_write_dist(grp_id, name, vec, offset, n_global)
290 integer(hid_t),
intent(in) :: grp_id
291 character(len=*),
intent(in) :: name
292 type(vector_t),
intent(in) :: vec
293 integer,
intent(in) :: offset, n_global
294 integer(hid_t) :: filespace, memspace, xf_id, dset_id
295 integer(hsize_t) :: ddim(1), dcount(1), doffset(1)
296 real(kind=rp) :: empty(1)
300 ddim(1) = int(n_global, hsize_t)
301 dcount(1) = int(vec%size(), hsize_t)
302 doffset(1) = int(offset, hsize_t)
304 call h5screate_simple_f(1, ddim, filespace, ierr)
305 call h5screate_simple_f(1, dcount, memspace, ierr)
306 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, doffset, dcount, &
309 call h5pcreate_f(h5p_dataset_xfer_f, xf_id, ierr)
310 call h5pset_dxpl_mpio_f(xf_id, h5fd_mpio_collective_f, ierr)
312 call h5dcreate_f(grp_id, name, sd_h5t_real(), filespace, dset_id, ierr)
313 if (vec%size() .gt. 0)
then
314 call h5dwrite_f(dset_id, sd_h5t_real(), vec%x, dcount, ierr, &
315 file_space_id = filespace, mem_space_id = memspace, &
318 call h5dwrite_f(dset_id, sd_h5t_real(), empty, dcount, ierr, &
319 file_space_id = filespace, mem_space_id = memspace, &
322 call h5dclose_f(dset_id, ierr)
324 call h5pclose_f(xf_id, ierr)
325 call h5sclose_f(memspace, ierr)
326 call h5sclose_f(filespace, ierr)
328 end subroutine sd_write_dist
339 subroutine sd_read_dist(grp_id, name, vec, offset, n_global)
340 integer(hid_t),
intent(in) :: grp_id
341 character(len=*),
intent(in) :: name
342 type(vector_t),
intent(inout) :: vec
343 integer,
intent(in) :: offset, n_global
344 integer(hid_t) :: filespace, memspace, xf_id, dset_id
345 integer(hsize_t) :: ddim(1), dcount(1), doffset(1)
346 real(kind=rp) :: empty(1)
349 ddim(1) = int(n_global, hsize_t)
350 dcount(1) = int(vec%size(), hsize_t)
351 doffset(1) = int(offset, hsize_t)
353 call h5screate_simple_f(1, ddim, filespace, ierr)
354 call h5screate_simple_f(1, dcount, memspace, ierr)
355 call h5sselect_hyperslab_f(filespace, h5s_select_set_f, doffset, dcount, &
358 call h5pcreate_f(h5p_dataset_xfer_f, xf_id, ierr)
359 call h5pset_dxpl_mpio_f(xf_id, h5fd_mpio_collective_f, ierr)
361 call h5dopen_f(grp_id, name, dset_id, ierr)
362 if (vec%size() .gt. 0)
then
363 call h5dread_f(dset_id, sd_h5t_real(), vec%x, dcount, ierr, &
364 file_space_id = filespace, mem_space_id = memspace, &
367 call h5dread_f(dset_id, sd_h5t_real(), empty, dcount, ierr, &
368 file_space_id = filespace, mem_space_id = memspace, &
371 call h5dclose_f(dset_id, ierr)
373 call h5pclose_f(xf_id, ierr)
374 call h5sclose_f(memspace, ierr)
375 call h5sclose_f(filespace, ierr)
377 end subroutine sd_read_dist
379end submodule steepest_descent_hdf5_io
Steepest descent optimizer with move limits.