From d79667eb0c57d729c1801ad58b2deb121aca0466 Mon Sep 17 00:00:00 2001 From: Scot Breitenfeld Date: Mon, 29 Jan 2024 13:13:33 -0600 Subject: [PATCH] Add API support for Fortran MPI_F08 module definitions. (#3959) * revert to using c-stub for _F08 MPI APIs * use mpi compiler wrappers for cmake and nvhpc --- .github/workflows/nvhpc-cmake.yml | 4 +- CMakeLists.txt | 7 + config/cmake/H5pubconf.h.in | 3 + configure.ac | 19 ++ fortran/src/CMakeLists.txt | 7 + fortran/src/H5Pff.F90 | 266 +++++++++++++++++++++-- fortran/src/H5config_f.inc.cmake | 8 + fortran/src/H5config_f.inc.in | 3 + fortran/src/hdf5_fortrandll.def.in | 12 +- fortran/testpar/CMakeLists.txt | 1 + fortran/testpar/Makefile.am | 2 +- fortran/testpar/mpi_param.F90 | 326 +++++++++++++++++++++++++++++ fortran/testpar/ptest.F90 | 10 + release_docs/RELEASE.txt | 5 + 14 files changed, 649 insertions(+), 24 deletions(-) create mode 100644 fortran/testpar/mpi_param.F90 diff --git a/.github/workflows/nvhpc-cmake.yml b/.github/workflows/nvhpc-cmake.yml index c6b338df8fa..17d6ec6b19d 100644 --- a/.github/workflows/nvhpc-cmake.yml +++ b/.github/workflows/nvhpc-cmake.yml @@ -33,8 +33,8 @@ jobs: echo 'deb [signed-by=/usr/share/keyrings/nvidia-hpcsdk-archive-keyring.gpg] https://developer.download.nvidia.com/hpc-sdk/ubuntu/amd64 /' | sudo tee /etc/apt/sources.list.d/nvhpc.list sudo apt-get update -y sudo apt-get install -y nvhpc-23-9 - echo "CC=nvc" >> $GITHUB_ENV - echo "FC=nvfortran" >> $GITHUB_ENV + echo "CC=/opt/nvidia/hpc_sdk/Linux_x86_64/23.9/comm_libs/openmpi4/bin/mpicc" >> $GITHUB_ENV + echo "FC=/opt/nvidia/hpc_sdk/Linux_x86_64/23.9/comm_libs/openmpi4/bin/mpifort" >> $GITHUB_ENV echo "NVHPCSDK=/opt/nvidia/hpc_sdk" >> $GITHUB_ENV echo "OMPI_CXX=/opt/nvidia/hpc_sdk/Linux_x86_64/23.9/compilers/bin/nvc++" >> $GITHUB_ENV echo "OMPI_CC=/opt/nvidia/hpc_sdk/Linux_x86_64/23.9/compilers/bin/nvc" >> $GITHUB_ENV diff --git a/CMakeLists.txt b/CMakeLists.txt index f536a4a9126..505d55d38fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1085,6 +1085,13 @@ if (EXISTS "${HDF5_SOURCE_DIR}/fortran" AND IS_DIRECTORY "${HDF5_SOURCE_DIR}/for if (MPI_Fortran_LINK_FLAGS) set (CMAKE_Fortran_EXE_LINKER_FLAGS "${MPI_Fortran_LINK_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}") endif () + # Check if MPI-3 Fortran 2008 module mpi_f08 is supported + if (MPI_Fortran_HAVE_F08_MODULE) + set (H5_HAVE_MPI_F08 1) + message (VERBOSE "MPI-3 Fortran 2008 module mpi_f08 is supported") + else () + message (VERBOSE "MPI-3 Fortran 2008 module mpi_f08 is NOT supported") + endif () endif () #option (HDF5_INSTALL_MOD_FORTRAN "Copy FORTRAN mod files to include directory (NO SHARED STATIC)" "NO") diff --git a/config/cmake/H5pubconf.h.in b/config/cmake/H5pubconf.h.in index 2534b8e2542..9fc9ae1143d 100644 --- a/config/cmake/H5pubconf.h.in +++ b/config/cmake/H5pubconf.h.in @@ -243,6 +243,9 @@ /* Define if we have parallel support */ #cmakedefine H5_HAVE_PARALLEL @H5_HAVE_PARALLEL@ +/* Define if MPI Fortran supports mpi_f08 module */ +#cmakedefine H5_HAVE_MPI_F08 @H5_HAVE_MPI_F08@ + /* Define if we have support for writing to filtered datasets in parallel */ #cmakedefine H5_HAVE_PARALLEL_FILTERED_WRITES @H5_HAVE_PARALLEL_FILTERED_WRITES@ diff --git a/configure.ac b/configure.ac index 9fd0fa519b9..97d4070a7c1 100644 --- a/configure.ac +++ b/configure.ac @@ -2840,6 +2840,25 @@ if test -n "$PARALLEL"; then AC_MSG_RESULT([yes])], [AC_MSG_RESULT([no])] ) + + AC_LANG_PUSH([Fortran]) + AC_MSG_CHECKING([for MPI-3 module mpi_f08]) + AC_LINK_IFELSE( + [AC_LANG_PROGRAM([], + [ + USE mpi_f08 + IMPLICIT NONE + TYPE(MPI_Comm) :: comm + TYPE(MPI_INFO) :: info + ] + ) + ], + [AC_DEFINE([HAVE_MPI_F08], [1], + [Define if mpi_f08 module exist]) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])] + ) + AC_LANG_POP(Fortran) fi ## ---------------------------------------------------------------------- diff --git a/fortran/src/CMakeLists.txt b/fortran/src/CMakeLists.txt index 60c0c3a96a2..4c280469056 100644 --- a/fortran/src/CMakeLists.txt +++ b/fortran/src/CMakeLists.txt @@ -24,6 +24,13 @@ if (WIN32) endif () endif () +if (H5_HAVE_MPI_F08) # MPI-3 module mpi_f08 supported + set (CMAKE_H5_HAVE_MPI_F08 1) +else () + set (H5_NOMPI_F08 ";") + set (CMAKE_H5_HAVE_MPI_F08 0) +endif () + # configure for Fortran preprocessor # Define Parallel variable for passing to H5config_f.inc.cmake diff --git a/fortran/src/H5Pff.F90 b/fortran/src/H5Pff.F90 index afd17f3dc32..90a74f7cf4f 100644 --- a/fortran/src/H5Pff.F90 +++ b/fortran/src/H5Pff.F90 @@ -49,6 +49,12 @@ MODULE H5P PRIVATE h5pget_integer, h5pget_char, h5pget_ptr PRIVATE h5pregister_integer, h5pregister_ptr PRIVATE h5pinsert_integer, h5pinsert_char, h5pinsert_ptr +#ifdef H5_HAVE_PARALLEL + PRIVATE h5pset_fapl_mpio_f90, h5pget_fapl_mpio_f90 +#ifdef H5_HAVE_MPI_F08 + PRIVATE h5pset_fapl_mpio_f08, h5pget_fapl_mpio_f08 +#endif +#endif #ifndef H5_DOXYGEN @@ -101,7 +107,6 @@ MODULE H5P MODULE PROCEDURE h5pinsert_ptr END INTERFACE - INTERFACE INTEGER(C_INT) FUNCTION H5Pset_fill_value(prp_id, type_id, fillvalue) & BIND(C, NAME='H5Pset_fill_value') @@ -182,6 +187,35 @@ END FUNCTION h5pinsert_c #endif #ifdef H5_HAVE_PARALLEL + + INTERFACE h5pset_fapl_mpio_f + MODULE PROCEDURE h5pset_fapl_mpio_f90 +#ifdef H5_HAVE_MPI_F08 + MODULE PROCEDURE h5pset_fapl_mpio_f08 +#endif + END INTERFACE + + INTERFACE h5pget_fapl_mpio_f + MODULE PROCEDURE h5pget_fapl_mpio_f90 +#ifdef H5_HAVE_MPI_F08 + MODULE PROCEDURE h5pget_fapl_mpio_f08 +#endif + END INTERFACE + + INTERFACE H5Pset_mpi_params_f + MODULE PROCEDURE H5Pset_mpi_params_f90 +#ifdef H5_HAVE_MPI_F08 + MODULE PROCEDURE H5Pset_mpi_params_f08 +#endif + END INTERFACE + + INTERFACE H5Pget_mpi_params_f + MODULE PROCEDURE H5Pget_mpi_params_f90 +#ifdef H5_HAVE_MPI_F08 + MODULE PROCEDURE H5Pget_mpi_params_f08 +#endif + END INTERFACE + #ifdef H5_HAVE_SUBFILING_VFD !> \addtogroup FH5P !> @{ @@ -5125,6 +5159,8 @@ END SUBROUTINE h5pget_file_image_f ! ********************************************************************* #ifdef H5_HAVE_PARALLEL + +#ifdef H5_DOXYGEN !> !! \ingroup FH5P !! @@ -5143,21 +5179,69 @@ SUBROUTINE h5pset_fapl_mpio_f(prp_id, comm, info, hdferr) INTEGER, INTENT(IN) :: comm INTEGER, INTENT(IN) :: info INTEGER, INTENT(OUT) :: hdferr + END SUBROUTINE h5pset_fapl_mpio_f +!> +!! \ingroup FH5P +!! +!! \brief Stores MPI IO communicator information to the file access property list. +!! +!! \note Supports MPI Fortran module mpi_f08 +!! +!! \param prp_id File access property list identifier. +!! \param comm MPI-3 communicator. +!! \param info MPI-3 info object. +!! \param hdferr \fortran_error +!! +!! See C API: @ref H5Pset_fapl_mpio() +!! + SUBROUTINE h5pset_fapl_mpio_f(prp_id, comm, info, hdferr) + IMPLICIT NONE + INTEGER(HID_T), INTENT(IN) :: prp_id + TYPE(MPI_COMM), INTENT(IN) :: comm + TYPE(MPI_INFO), INTENT(IN) :: info + INTEGER, INTENT(OUT) :: hdferr + END SUBROUTINE h5pset_fapl_mpio_f + +#else + + SUBROUTINE h5pset_fapl_mpio_f90(prp_id, comm, info, hdferr) + IMPLICIT NONE + INTEGER(HID_T), INTENT(IN) :: prp_id + INTEGER, INTENT(IN) :: comm + INTEGER, INTENT(IN) :: info + INTEGER, INTENT(OUT) :: hdferr INTERFACE INTEGER FUNCTION h5pset_fapl_mpio_c(prp_id, comm, info) & BIND(C,NAME='h5pset_fapl_mpio_c') IMPORT :: HID_T IMPLICIT NONE - INTEGER(HID_T), INTENT(IN) :: prp_id - INTEGER , INTENT(IN) :: comm - INTEGER , INTENT(IN) :: info + INTEGER(HID_T) :: prp_id + INTEGER :: comm + INTEGER :: info END FUNCTION h5pset_fapl_mpio_c END INTERFACE hdferr = h5pset_fapl_mpio_c(prp_id, comm, info) - END SUBROUTINE h5pset_fapl_mpio_f + END SUBROUTINE h5pset_fapl_mpio_f90 +#ifdef H5_HAVE_MPI_F08 + SUBROUTINE h5pset_fapl_mpio_f08(prp_id, comm, info, hdferr) + USE mpi_f08 + IMPLICIT NONE + INTEGER(HID_T), INTENT(IN) :: prp_id + TYPE(MPI_COMM), INTENT(IN) :: comm + TYPE(MPI_INFO), INTENT(IN) :: info + INTEGER, INTENT(OUT) :: hdferr + + CALL h5pset_fapl_mpio_f90(prp_id, comm%mpi_val, info%mpi_val, hdferr) + + END SUBROUTINE h5pset_fapl_mpio_f08 +#endif + +#endif + +#ifdef H5_DOXYGEN !> !! \ingroup FH5P !! @@ -5168,9 +5252,44 @@ END SUBROUTINE h5pset_fapl_mpio_f !! \param info MPI-2 info object. !! \param hdferr \fortran_error !! +!! \attention It is the responsibility of the application to free the MPI objects. +!! !! See C API: @ref H5Pget_fapl_mpio() !! - SUBROUTINE h5pget_fapl_mpio_f(prp_id, comm, info, hdferr) +SUBROUTINE h5pget_fapl_mpio_f(prp_id, comm, info, hdferr) + IMPLICIT NONE + INTEGER(HID_T), INTENT(IN) :: prp_id + INTEGER, INTENT(OUT) :: comm + INTEGER, INTENT(OUT) :: info + INTEGER, INTENT(OUT) :: hdferr +END SUBROUTINE h5pget_fapl_mpio_f +!> +!! \ingroup FH5P +!! +!! \brief Returns MPI communicator information. +!! +!! \note Supports MPI Fortran module mpi_f08 +!! +!! \param prp_id File access property list identifier. +!! \param comm MPI-3 communicator. +!! \param info MPI-3 info object. +!! \param hdferr \fortran_error +!! +!! \attention It is the responsibility of the application to free the MPI objects. +!! +!! See C API: @ref H5Pget_fapl_mpio() +!! +SUBROUTINE h5pget_fapl_mpio_f(prp_id, comm, info, hdferr) + IMPLICIT NONE + INTEGER(HID_T), INTENT(IN) :: prp_id + TYPE(MPI_COMM), INTENT(OUT) :: comm + TYPE(MPI_INFO), INTENT(OUT) :: info + INTEGER , INTENT(OUT) :: hdferr +END SUBROUTINE h5pget_fapl_mpio_f + +#else + + SUBROUTINE h5pget_fapl_mpio_f90(prp_id, comm, info, hdferr) IMPLICIT NONE INTEGER(HID_T), INTENT(IN) :: prp_id INTEGER, INTENT(OUT) :: comm @@ -5181,15 +5300,30 @@ INTEGER FUNCTION h5pget_fapl_mpio_c(prp_id, comm, info) & BIND(C,NAME='h5pget_fapl_mpio_c') IMPORT :: HID_T IMPLICIT NONE - INTEGER(HID_T), INTENT(IN) :: prp_id - INTEGER , INTENT(OUT) :: comm - INTEGER , INTENT(OUT) :: info + INTEGER(HID_T) :: prp_id + INTEGER :: comm + INTEGER :: info END FUNCTION h5pget_fapl_mpio_c END INTERFACE hdferr = h5pget_fapl_mpio_c(prp_id, comm, info) - END SUBROUTINE h5pget_fapl_mpio_f + END SUBROUTINE h5pget_fapl_mpio_f90 + +#ifdef H5_HAVE_MPI_F08 + SUBROUTINE h5pget_fapl_mpio_f08(prp_id, comm, info, hdferr) + USE mpi_f08 + IMPLICIT NONE + INTEGER(HID_T), INTENT(IN) :: prp_id + TYPE(MPI_COMM), INTENT(OUT) :: comm + TYPE(MPI_INFO), INTENT(OUT) :: info + INTEGER, INTENT(OUT) :: hdferr + + CALL h5pget_fapl_mpio_f90(prp_id, comm%mpi_val, info%mpi_val, hdferr) + + END SUBROUTINE h5pget_fapl_mpio_f08 +#endif +#endif #ifdef H5_HAVE_SUBFILING_VFD !> @@ -5376,14 +5510,15 @@ END FUNCTION H5Pget_mpio_no_collective_cause END SUBROUTINE h5pget_mpio_no_collective_cause_f +#ifdef H5_DOXYGEN !> !! \ingroup FH5P !! -!! \brief Set the MPI communicator and info. +!! \brief Set the MPI communicator and information. !! !! \param prp_id File access property list identifier. -!! \param comm The MPI communicator. -!! \param info The MPI info object. +!! \param comm MPI-2 communicator. +!! \param info MPI-2 info object. !! \param hdferr \fortran_error !! !! See C API: @ref H5Pset_mpi_params() @@ -5394,6 +5529,37 @@ SUBROUTINE H5Pset_mpi_params_f(prp_id, comm, info, hdferr) INTEGER , INTENT(IN) :: comm INTEGER , INTENT(IN) :: info INTEGER , INTENT(OUT) :: hdferr + END SUBROUTINE H5Pset_mpi_params_f +!> +!! \ingroup FH5P +!! +!! \brief Set the MPI communicator and information. +!! +!! \note Supports MPI Fortran module mpi_f08 +!! +!! \param prp_id File access property list identifier. +!! \param comm MPI-3 communicator. +!! \param info MPI-3 info object. +!! \param hdferr \fortran_error +!! +!! See C API: @ref H5Pset_mpi_params() +!! + SUBROUTINE H5Pset_mpi_params_f(prp_id, comm, info, hdferr) + IMPLICIT NONE + INTEGER(HID_T), INTENT(IN) :: prp_id + TYPE(MPI_COMM), INTENT(IN) :: comm + TYPE(MPI_INFO), INTENT(IN) :: info + INTEGER , INTENT(OUT) :: hdferr + END SUBROUTINE H5Pset_mpi_params_f + +#else + + SUBROUTINE H5Pset_mpi_params_f90(prp_id, comm, info, hdferr) + IMPLICIT NONE + INTEGER(HID_T), INTENT(IN) :: prp_id + INTEGER , INTENT(IN) :: comm + INTEGER , INTENT(IN) :: info + INTEGER , INTENT(OUT) :: hdferr INTERFACE INTEGER FUNCTION h5pset_mpi_params_c(prp_id, comm, info) & @@ -5408,16 +5574,33 @@ END FUNCTION H5pset_mpi_params_c hdferr = H5Pset_mpi_params_c(prp_id, comm, info) - END SUBROUTINE H5Pset_mpi_params_f + END SUBROUTINE H5Pset_mpi_params_f90 + +#ifdef H5_HAVE_MPI_F08 + SUBROUTINE H5Pset_mpi_params_f08(prp_id, comm, info, hdferr) + USE mpi_f08 + IMPLICIT NONE + INTEGER(HID_T), INTENT(IN) :: prp_id + TYPE(MPI_COMM), INTENT(IN) :: comm + TYPE(MPI_INFO), INTENT(IN) :: info + INTEGER , INTENT(OUT) :: hdferr + + CALL H5Pset_mpi_params_f90(prp_id, comm%mpi_val, info%mpi_val, hdferr) + + END SUBROUTINE H5Pset_mpi_params_f08 +#endif + +#endif +#ifdef H5_DOXYGEN !> !! \ingroup FH5P !! !! \brief Get the MPI communicator and info. !! !! \param prp_id File access property list identifier. -!! \param comm The MPI communicator. -!! \param info The MPI info object. +!! \param comm MPI-2 communicator. +!! \param info MPI-2 info object. !! \param hdferr \fortran_error !! !! See C API: @ref H5Pget_mpi_params() @@ -5428,6 +5611,39 @@ SUBROUTINE H5Pget_mpi_params_f(prp_id, comm, info, hdferr) INTEGER , INTENT(OUT) :: comm INTEGER , INTENT(OUT) :: info INTEGER , INTENT(OUT) :: hdferr + END SUBROUTINE H5Pget_mpi_params_f +!> +!! \ingroup FH5P +!! +!! \brief Get the MPI communicator and information. +!! +!! \note Supports MPI Fortran module mpi_f08 +!! +!! \param prp_id File access property list identifier. +!! \param comm MPI-3 communicator. +!! \param info MPI-3 info object. +!! \param hdferr \fortran_error +!! +!! \attention It is the responsibility of the application to free the MPI objects. +!! +!! See C API: @ref H5Pget_mpi_params() +!! + SUBROUTINE H5Pget_mpi_params_f(prp_id, comm, info, hdferr) + IMPLICIT NONE + INTEGER(HID_T), INTENT(IN) :: prp_id + TYPE(MPI_COMM), INTENT(OUT) :: comm + TYPE(MPI_INFO), INTENT(OUT) :: info + INTEGER , INTENT(OUT) :: hdferr + END SUBROUTINE H5Pget_mpi_params_f + +#else + + SUBROUTINE H5Pget_mpi_params_f90(prp_id, comm, info, hdferr) + IMPLICIT NONE + INTEGER(HID_T), INTENT(IN) :: prp_id + INTEGER , INTENT(OUT) :: comm + INTEGER , INTENT(OUT) :: info + INTEGER , INTENT(OUT) :: hdferr INTERFACE INTEGER FUNCTION h5pget_mpi_params_c(prp_id, comm, info) & @@ -5442,7 +5658,23 @@ END FUNCTION H5pget_mpi_params_c hdferr = H5Pget_mpi_params_c(prp_id, comm, info) - END SUBROUTINE H5Pget_mpi_params_f + END SUBROUTINE H5Pget_mpi_params_f90 + +#ifdef H5_HAVE_MPI_F08 + SUBROUTINE H5Pget_mpi_params_f08(prp_id, comm, info, hdferr) + USE mpi_f08 + IMPLICIT NONE + INTEGER(HID_T), INTENT(IN) :: prp_id + TYPE(MPI_COMM), INTENT(OUT) :: comm + TYPE(MPI_INFO), INTENT(OUT) :: info + INTEGER , INTENT(OUT) :: hdferr + + CALL H5Pget_mpi_params_f90(prp_id, comm%mpi_val, info%mpi_val, hdferr) + + END SUBROUTINE H5Pget_mpi_params_f08 +#endif + +#endif !> !! \ingroup FH5P diff --git a/fortran/src/H5config_f.inc.cmake b/fortran/src/H5config_f.inc.cmake index 77ff7071640..e6fa7b93503 100644 --- a/fortran/src/H5config_f.inc.cmake +++ b/fortran/src/H5config_f.inc.cmake @@ -19,6 +19,14 @@ #define H5_HAVE_PARALLEL #endif +! Define if MPI supports mpi_f08 module +#cmakedefine01 CMAKE_H5_HAVE_MPI_F08 +#if CMAKE_H5_HAVE_MPI_F08 == 0 +#undef H5_HAVE_MPI_F08 +#else +#define H5_HAVE_MPI_F08 +#endif + ! Define if there is subfiling support #cmakedefine01 CMAKE_H5_HAVE_SUBFILING_VFD #if CMAKE_H5_HAVE_SUBFILING_VFD == 0 diff --git a/fortran/src/H5config_f.inc.in b/fortran/src/H5config_f.inc.in index afcfa6e0f76..7f522558b55 100644 --- a/fortran/src/H5config_f.inc.in +++ b/fortran/src/H5config_f.inc.in @@ -17,6 +17,9 @@ ! Define if we have parallel support #undef HAVE_PARALLEL +! Define if MPI supports mpi_f08 module +#undef HAVE_MPI_F08 + ! Define if we have subfiling support #undef HAVE_SUBFILING_VFD diff --git a/fortran/src/hdf5_fortrandll.def.in b/fortran/src/hdf5_fortrandll.def.in index ccb770ae362..e29488f8cee 100644 --- a/fortran/src/hdf5_fortrandll.def.in +++ b/fortran/src/hdf5_fortrandll.def.in @@ -421,14 +421,18 @@ H5P_mp_H5PSET_FILE_SPACE_PAGE_SIZE_F H5P_mp_H5PGET_FILE_SPACE_PAGE_SIZE_F H5P_mp_H5PGET_ACTUAL_SELECTION_IO_MODE_F ; Parallel -@H5_NOPAREXP@H5P_mp_H5PSET_FAPL_MPIO_F -@H5_NOPAREXP@H5P_mp_H5PGET_FAPL_MPIO_F +@H5_NOPAREXP@H5P_mp_H5PSET_FAPL_MPIO_F90 +@H5_NOPAREXP@@H5_NOMPI_F08@H5P_mp_H5PSET_FAPL_MPIO_F08 +@H5_NOPAREXP@H5P_mp_H5PGET_FAPL_MPIO_F90 +@H5_NOPAREXP@@H5_NOMPI_F08@H5P_mp_H5PGET_FAPL_MPIO_F08 @H5_NOPAREXP@@H5_NOSUBFILING@H5P_mp_H5PSET_FAPL_SUBFILING_F @H5_NOPAREXP@@H5_NOSUBFILING@H5P_mp_H5PGET_FAPL_SUBFILING_F @H5_NOPAREXP@@H5_NOSUBFILING@H5P_mp_H5PSET_FAPL_IOC_F @H5_NOPAREXP@@H5_NOSUBFILING@H5P_mp_H5PGET_FAPL_IOC_F -@H5_NOPAREXP@H5P_mp_H5PSET_MPI_PARAMS_F -@H5_NOPAREXP@H5P_mp_H5PGET_MPI_PARAMS_F +@H5_NOPAREXP@H5P_mp_H5PSET_MPI_PARAMS_F90 +@H5_NOPAREXP@@H5_NOMPI_F08@H5P_mp_H5PSET_MPI_PARAMS_F08 +@H5_NOPAREXP@H5P_mp_H5PGET_MPI_PARAMS_F90 +@H5_NOPAREXP@@H5_NOMPI_F08@H5P_mp_H5PGET_MPI_PARAMS_F08 @H5_NOPAREXP@H5P_mp_H5PSET_DXPL_MPIO_F @H5_NOPAREXP@H5P_mp_H5PGET_DXPL_MPIO_F @H5_NOPAREXP@H5P_mp_H5PGET_MPIO_ACTUAL_IO_MODE_F diff --git a/fortran/testpar/CMakeLists.txt b/fortran/testpar/CMakeLists.txt index e8f010721fe..4d3a3309a7f 100644 --- a/fortran/testpar/CMakeLists.txt +++ b/fortran/testpar/CMakeLists.txt @@ -20,6 +20,7 @@ add_executable (parallel_test ptest.F90 hyper.F90 mdset.F90 + mpi_param.F90 multidsetrw.F90 ) target_include_directories (parallel_test diff --git a/fortran/testpar/Makefile.am b/fortran/testpar/Makefile.am index 1c374090601..3df1fee8f09 100644 --- a/fortran/testpar/Makefile.am +++ b/fortran/testpar/Makefile.am @@ -39,7 +39,7 @@ check_PROGRAMS=$(TEST_PROG_PARA) CHECK_CLEANFILES+=parf[12].h5 h5*_tests.h5 subf.h5* *.mod # Test source files -parallel_test_SOURCES=ptest.F90 hyper.F90 mdset.F90 multidsetrw.F90 +parallel_test_SOURCES=ptest.F90 hyper.F90 mdset.F90 multidsetrw.F90 mpi_param.F90 subfiling_test_SOURCES=subfiling.F90 async_test_SOURCES=async.F90 diff --git a/fortran/testpar/mpi_param.F90 b/fortran/testpar/mpi_param.F90 new file mode 100644 index 00000000000..ba4eaaae963 --- /dev/null +++ b/fortran/testpar/mpi_param.F90 @@ -0,0 +1,326 @@ +! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * +! Copyright by The HDF Group. * +! All rights reserved. * +! * +! This file is part of HDF5. The full HDF5 copyright notice, including * +! terms governing use, modification, and redistribution, is contained in * +! the COPYING file, which can be found at the root of the source code * +! distribution tree, or in https://www.hdfgroup.org/licenses. * +! If you do not have access to either file, you may request a copy from * +! help@hdfgroup.org. * +! * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + +#include + +! +! writes/reads dataset by hyperslabs +! + +SUBROUTINE mpi_param_03(nerrors) + + USE MPI + USE HDF5 + USE TH5_MISC + USE TH5_MISC_GEN + + IMPLICIT NONE + INTEGER, INTENT(inout) :: nerrors ! number of errors + + INTEGER :: hdferror ! HDF hdferror flag + INTEGER(hid_t) :: fapl_id ! file access identifier + INTEGER :: mpi_size, mpi_size_ret ! number of processes in the group of communicator + INTEGER :: mpierror ! MPI hdferror flag + INTEGER :: mpi_rank ! rank of the calling process in the communicator + + INTEGER :: info, info_ret + INTEGER :: comm, comm_ret + INTEGER :: nkeys + LOGICAL :: flag + INTEGER :: iconfig + CHARACTER(LEN=4) , PARAMETER :: in_key="host" + CHARACTER(LEN=10), PARAMETER :: in_value="myhost.org" + + CHARACTER(LEN=MPI_MAX_INFO_KEY) :: key, value + + ! Get the original sizes + CALL mpi_comm_rank( MPI_COMM_WORLD, mpi_rank, mpierror ) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_COMM_RANK *FAILED*" + nerrors = nerrors + 1 + ENDIF + CALL mpi_comm_size( MPI_COMM_WORLD, mpi_size, mpierror ) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_COMM_SIZE *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + + DO iconfig = 1, 2 + + ! Create the file access property + CALL h5pcreate_f(H5P_FILE_ACCESS_F, fapl_id, hdferror) + CALL check("h5pcreate_f", hdferror, nerrors) + + ! Split the communicator + IF(mpi_rank.EQ.0)THEN + CALL MPI_Comm_split(MPI_COMM_WORLD, 1, mpi_rank, comm, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_COMM_SPLIT *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + ELSE + CALL MPI_Comm_split(MPI_COMM_WORLD, 0, mpi_rank, comm, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_COMM_SPLIT *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + ENDIF + + ! Create and set an MPI INFO parameter + + CALL MPI_Info_create(info, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_INFO_CREATE *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + CALL MPI_Info_set(info, in_key, in_value, mpierror ) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_INFO_SET *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + + IF(iconfig.EQ.1)THEN + ! Set and get the MPI parameters + CALL h5pset_fapl_mpio_f(fapl_id, comm, info, hdferror) + CALL check("h5pset_fapl_mpio_f", hdferror, nerrors) + + CALL h5pget_fapl_mpio_f(fapl_id, comm_ret, info_ret, hdferror) + CALL check("h5pget_fapl_mpio_f", hdferror, nerrors) + ELSE + CALL h5pset_mpi_params_f(fapl_id, comm, info, hdferror) + CALL check("h5pset_mpi_params_f", hdferror, nerrors) + + CALL h5pget_mpi_params_f(fapl_id, comm_ret, info_ret, hdferror) + CALL check("h5pget_mpi_params_f", hdferror, nerrors) + ENDIF + + + ! Check comm returned + CALL mpi_comm_size(comm_ret, mpi_size_ret, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_COMM_SIZE *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + IF (mpi_rank.EQ.0)THEN + CALL VERIFY("h5pget_fapl_mpio_f", mpi_size_ret, 1, hdferror) + ELSE + CALL VERIFY("h5pget_fapl_mpio_f", mpi_size_ret, mpi_size-1, hdferror) + ENDIF + + ! Check info returned + CALL MPI_info_get_nkeys( info_ret, nkeys, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_INFO_GET_NKEYS *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + CALL VERIFY("h5pget_fapl_mpio_f", nkeys, 1, hdferror) + + CALL MPI_Info_get_nthkey(info_ret, 0, key, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_INFO_GET_NTHKEY *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + CALL VERIFY("h5pget_fapl_mpio_f", TRIM(key), in_key, hdferror) + + CALL MPI_Info_get(info, key, MPI_MAX_INFO_KEY, value, flag, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_INFO_GET *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + CALL VERIFY("h5pget_fapl_mpio_f", flag, .TRUE., hdferror) + CALL VERIFY("h5pget_fapl_mpio_f", TRIM(value), in_value, hdferror) + + ! Free the MPI resources + CALL MPI_info_free(info_ret, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_INFO_FREE *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + CALL MPI_comm_free(comm_ret, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_COMM_FREE *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + CALL MPI_info_free(info, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_INFO_FREE *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + CALL MPI_comm_free(comm, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_COMM_FREE *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + + CALL h5pclose_f(fapl_id, hdferror) + CALL check("h5pclose_f", hdferror, nerrors) + ENDDO + +END SUBROUTINE mpi_param_03 + +SUBROUTINE mpi_param_08(nerrors) + +#ifdef H5_HAVE_MPI_F08 + + USE MPI_F08 + USE HDF5 + USE TH5_MISC + USE TH5_MISC_GEN + + IMPLICIT NONE + INTEGER, INTENT(inout) :: nerrors ! number of errors + + INTEGER :: hdferror ! HDF hdferror flag + INTEGER(hid_t) :: fapl_id ! file access identifier + INTEGER :: mpi_size, mpi_size_ret ! number of processes in the group of communicator + INTEGER :: mpierror ! MPI hdferror flag + INTEGER :: mpi_rank ! rank of the calling process in the communicator + + TYPE(MPI_INFO) :: info, info_ret + TYPE(MPI_COMM) :: comm, comm_ret + INTEGER :: nkeys + LOGICAL :: flag + INTEGER :: iconfig + CHARACTER(LEN=4) , PARAMETER :: in_key="host" + CHARACTER(LEN=10), PARAMETER :: in_value="myhost.org" + + CHARACTER(LEN=MPI_MAX_INFO_KEY) :: key, value + + ! Get the original sizes + CALL mpi_comm_rank( MPI_COMM_WORLD, mpi_rank, mpierror ) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_COMM_RANK *FAILED*" + nerrors = nerrors + 1 + ENDIF + CALL mpi_comm_size( MPI_COMM_WORLD, mpi_size, mpierror ) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_COMM_SIZE *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + + DO iconfig = 1, 2 + + ! Create the file access property + CALL h5pcreate_f(H5P_FILE_ACCESS_F, fapl_id, hdferror) + CALL check("h5pcreate_f", hdferror, nerrors) + + ! Split the communicator + IF(mpi_rank.EQ.0)THEN + CALL MPI_Comm_split(MPI_COMM_WORLD, 1, mpi_rank, comm, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_COMM_SPLIT *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + ELSE + CALL MPI_Comm_split(MPI_COMM_WORLD, 0, mpi_rank, comm, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_COMM_SPLIT *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + ENDIF + + ! Create and set an MPI INFO parameter + + CALL MPI_Info_create(info, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_INFO_CREATE *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + CALL MPI_Info_set(info, in_key, in_value, mpierror ) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_INFO_SET *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + + IF(iconfig.EQ.1)THEN + ! Set and get the MPI parameters + CALL h5pset_fapl_mpio_f(fapl_id, comm, info, hdferror) + CALL check("h5pset_fapl_mpio_f", hdferror, nerrors) + + CALL h5pget_fapl_mpio_f(fapl_id, comm_ret, info_ret, hdferror) + CALL check("h5pget_fapl_mpio_f", hdferror, nerrors) + ELSE + CALL h5pset_mpi_params_f(fapl_id, comm, info, hdferror) + CALL check("h5pset_mpi_params_f", hdferror, nerrors) + + CALL h5pget_mpi_params_f(fapl_id, comm_ret, info_ret, hdferror) + CALL check("h5pget_mpi_params_f", hdferror, nerrors) + ENDIF + + + ! Check comm returned + CALL mpi_comm_size(comm_ret, mpi_size_ret, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_COMM_SIZE *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + IF (mpi_rank.EQ.0)THEN + CALL VERIFY("h5pget_fapl_mpio_f", mpi_size_ret, 1, hdferror) + ELSE + CALL VERIFY("h5pget_fapl_mpio_f", mpi_size_ret, mpi_size-1, hdferror) + ENDIF + + ! Check info returned + CALL MPI_info_get_nkeys( info_ret, nkeys, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_INFO_GET_NKEYS *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + CALL VERIFY("h5pget_fapl_mpio_f", nkeys, 1, hdferror) + + CALL MPI_Info_get_nthkey(info_ret, 0, key, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_INFO_GET_NTHKEY *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + CALL VERIFY("h5pget_fapl_mpio_f", TRIM(key), in_key, hdferror) + + CALL MPI_Info_get(info, key, MPI_MAX_INFO_KEY, value, flag, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_INFO_GET *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + CALL VERIFY("h5pget_fapl_mpio_f", flag, .TRUE., hdferror) + CALL VERIFY("h5pget_fapl_mpio_f", TRIM(value), in_value, hdferror) + + ! Free the MPI resources + CALL MPI_info_free(info_ret, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_INFO_FREE *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + CALL MPI_comm_free(comm_ret, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_COMM_FREE *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + CALL MPI_info_free(info, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_INFO_FREE *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + CALL MPI_comm_free(comm, mpierror) + IF (mpierror .NE. MPI_SUCCESS) THEN + WRITE(*,*) "MPI_COMM_FREE *FAILED* Process = ", mpi_rank + nerrors = nerrors + 1 + ENDIF + + CALL h5pclose_f(fapl_id, hdferror) + CALL check("h5pclose_f", hdferror, nerrors) + ENDDO +#else + INTEGER, INTENT(inout) :: nerrors ! number of errors + nerrors = -1 ! Skip test +#endif + +END SUBROUTINE mpi_param_08 + diff --git a/fortran/testpar/ptest.F90 b/fortran/testpar/ptest.F90 index b754e297cc0..d2e9d105703 100644 --- a/fortran/testpar/ptest.F90 +++ b/fortran/testpar/ptest.F90 @@ -58,6 +58,16 @@ PROGRAM parallel_test IF(mpi_rank==0) CALL write_test_header("COMPREHENSIVE PARALLEL FORTRAN TESTS") + ret_total_error = 0 + CALL mpi_param_03(ret_total_error) + IF(mpi_rank==0) CALL write_test_status(ret_total_error, & + 'Testing MPI communicator and info (F03)', total_error) + + ret_total_error = 0 + CALL mpi_param_08(ret_total_error) + IF(mpi_rank==0) CALL write_test_status(ret_total_error, & + 'Testing MPI communicator and info (F08)', total_error) + ! ! test write/read dataset by hyperslabs (contiguous/chunk) with independent/collective MPI I/O ! diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt index de02a66a471..aeb59c26f21 100644 --- a/release_docs/RELEASE.txt +++ b/release_docs/RELEASE.txt @@ -388,6 +388,11 @@ New Features Fortran Library: ---------------- + - Add API support for Fortran MPI_F08 module definitions: + Adds support for MPI's MPI_F08 module datatypes: type(MPI_COMM) and type(MPI_INFO) for HDF5 APIs: + H5PSET_FAPL_MPIO_F, H5PGET_FAPL_MPIO_F, H5PSET_MPI_PARAMS_F, H5PGET_MPI_PARAMS_F + Ref. #3951 + - Added Fortran APIs: H5FGET_INTENT_F, H5SSEL_ITER_CREATE_F, H5SSEL_ITER_GET_SEQ_LIST_F, H5SSEL_ITER_CLOSE_F, H5S_mp_H5SSEL_ITER_RESET_F