diff --git a/config/ompi_config_files.m4 b/config/ompi_config_files.m4 index 3ea394a1104..926e0388c10 100644 --- a/config/ompi_config_files.m4 +++ b/config/ompi_config_files.m4 @@ -42,8 +42,10 @@ AC_DEFUN([OMPI_CONFIG_FILES],[ ompi/mpi/fortran/use-mpi-f08/Makefile ompi/mpi/fortran/use-mpi-f08/base/Makefile ompi/mpi/fortran/use-mpi-f08/bindings/Makefile + ompi/mpi/fortran/use-mpi-f08/ts/Makefile ompi/mpi/fortran/use-mpi-f08/mod/Makefile ompi/mpi/fortran/use-mpi-f08/mod/mpi-f08-interfaces.h + ompi/mpi/fortran/use-mpi-f08/mod/mpi-f08-rename.h ompi/mpi/fortran/mpiext-use-mpi/Makefile ompi/mpi/fortran/mpiext-use-mpi-f08/Makefile ompi/mpi/bindings/ompi_bindings/compiler.py diff --git a/config/ompi_setup_mpi_fortran.m4 b/config/ompi_setup_mpi_fortran.m4 index 1b695bc8555..f3e7aa02610 100644 --- a/config/ompi_setup_mpi_fortran.m4 +++ b/config/ompi_setup_mpi_fortran.m4 @@ -460,16 +460,9 @@ end program]])], # We need to have ignore TKR or the ISO Fortran bindings functionality to build the mpi_f08 # module - AS_IF([test $OMPI_TRY_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS], - [AS_IF([test $OMPI_FORTRAN_HAVE_IGNORE_TKR -eq 1], - [OMPI_BUILD_FORTRAN_BINDINGS=$OMPI_FORTRAN_USEMPIF08_BINDINGS - OMPI_FORTRAN_F08_PREDECL=$OMPI_FORTRAN_IGNORE_TKR_PREDECL - OMPI_FORTRAN_F08_TYPE=$OMPI_FORTRAN_IGNORE_TKR_TYPE - ]) - AS_IF([test $OMPI_FORTRAN_HAVE_TS -eq 1], - [OMPI_BUILD_FORTRAN_BINDINGS=$OMPI_FORTRAN_USEMPIF08_BINDINGS - OMPI_MPI_SUBARRAYS_SUPPORTED=.true. - OMPI_MPI_ASYNC_PROTECTS_NONBLOCKING=.true.])]) + AS_IF([test $OMPI_TRY_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS && \ + test $OMPI_FORTRAN_HAVE_IGNORE_TKR -eq 1], + [OMPI_BUILD_FORTRAN_BINDINGS=$OMPI_FORTRAN_USEMPIF08_BINDINGS]) # The overall "_BIND_C" variable will be set to 1 if we have all # the necessary forms of BIND(C) @@ -667,7 +660,7 @@ end type test_mpi_handle], AS_IF([test $OMPI_MIN_REQUIRED_FORTRAN_BINDINGS -gt $OMPI_BUILD_FORTRAN_BINDINGS], [AC_MSG_ERROR([Cannot build requested Fortran bindings, aborting])]) - dnl AC_CONFIG_FILES([ompi/mpi/fortran/use-mpi-f08/bindings/mpi-f-interfaces-bind.h]) + AC_CONFIG_FILES([ompi/mpi/fortran/use-mpi-f08/bindings/mpi-f-interfaces-bind.h]) # ------------------- # mpif.h final setup @@ -899,11 +892,11 @@ end type test_mpi_handle], AS_IF([test $OMPI_FORTRAN_HAVE_TS -eq 1], [OMPI_F08_IGNORE_TKR_TYPE="type(*), dimension(..)" - OMPI_F08_IGNORE_TKR_PREDECL="no attribute required for" + OMPI_F08_IGNORE_TKR_PREDECL="! no attribute required for" OMPI_F08_BINDINGS_EXTENSION="ts" OMPI_F08_BINDINGS_TS_SUFFIX="ts"], [OMPI_F08_IGNORE_TKR_TYPE=$OMPI_FORTRAN_IGNORE_TKR_TYPE - OMPI_F08_IGNORE_TKR_PREDECL=${OMPI_FORTRAN_IGNORE_TKR_PREDECL:1} + OMPI_F08_IGNORE_TKR_PREDECL=$OMPI_FORTRAN_IGNORE_TKR_PREDECL OMPI_F08_BINDINGS_EXTENSION="f" OMPI_F08_BINDINGS_TS_SUFFIX=""]) AC_SUBST(OMPI_F08_BINDINGS_EXTENSION) diff --git a/ompi/Makefile.am b/ompi/Makefile.am index f2709494f9a..e951e0d8e45 100644 --- a/ompi/Makefile.am +++ b/ompi/Makefile.am @@ -88,6 +88,7 @@ SUBDIRS = \ mpi/fortran/use-mpi-f08/base \ mpi/fortran/use-mpi-f08/mod \ mpi/fortran/use-mpi-f08/bindings \ + mpi/fortran/use-mpi-f08/ts \ $(OMPI_MPIEXT_USEMPIF08_DIRS) \ mpi/fortran/use-mpi-f08 \ mpi/fortran/mpiext-use-mpi-f08 \ @@ -120,6 +121,7 @@ DIST_SUBDIRS = \ mpi/fortran/use-mpi-f08/base \ mpi/fortran/use-mpi-f08/mod \ mpi/fortran/use-mpi-f08/bindings \ + mpi/fortran/use-mpi-f08/ts \ mpi/fortran/mpiext-use-mpi-f08 \ mpi/java \ $(OMPI_MPIEXT_ALL_SUBDIRS) \ diff --git a/ompi/mpi/fortran/configure-fortran-output.h.in b/ompi/mpi/fortran/configure-fortran-output.h.in index ed239693b15..740fa9bd2c2 100644 --- a/ompi/mpi/fortran/configure-fortran-output.h.in +++ b/ompi/mpi/fortran/configure-fortran-output.h.in @@ -43,10 +43,23 @@ ! Line 2 of the ignore TKR syntax #define OMPI_FORTRAN_IGNORE_TKR_TYPE @OMPI_FORTRAN_IGNORE_TKR_TYPE@ -! f08 TKR syntax (w/o TS 29113) -#define OMPI_F08_IGNORE_TKR_PREDECL @OMPI_F08_IGNORE_TKR_PREDECL@ +! The Fortran ISO C type type(*), dimension(..) is not (yet) supported by all compilers. +! If it is supported, OMPI_F08_IGNORE_TKR_TYPE will be type(*), dimension(..). +! Otherwise, it will be the same value as OMPI_FORTRAN_IGNORE_TKR_TYPE. #define OMPI_F08_IGNORE_TKR_TYPE @OMPI_F08_IGNORE_TKR_TYPE@ +! If the Fortran compiler supports type(*), dimension(..), this macro will be "_desc" +! so that the F08 descriptor-enabled Open MPI Fortran back-end functions are invoked. +! Otherwise, it will be "_f" so that the non-F08-descriptor Open MPI Fortran back-end functions are invoked. +#define OMPI_F08_BINDINGS_EXTENSION @OMPI_F08_BINDINGS_EXTENSION@ + +! If the Fortran compiler supports type(*), dimension(..), this macro will be empty +! (i.e., we do not want to ignore the TKR of the buf parameter). +! Otherwise, it will be set to !GCC$ ATTRIBUTES NO_ARG_CHECK :: buf so that the GCC compiler +! (and related compilers, such as the Intel compiler) will ignore the TKR of the buf dummy argument. + +#define OMPI_F08_GCC_ATTRIBUTES(buf) @OMPI_F08_GCC_ATTRIBUTES@ + #define OMPI_FORTRAN_BUILD_SIZEOF @OMPI_FORTRAN_BUILD_SIZEOF@ ! Integers diff --git a/ompi/mpi/fortran/use-mpi-f08/Makefile.am b/ompi/mpi/fortran/use-mpi-f08/Makefile.am index 69d8b125d0d..31230f82d35 100644 --- a/ompi/mpi/fortran/use-mpi-f08/Makefile.am +++ b/ompi/mpi/fortran/use-mpi-f08/Makefile.am @@ -36,8 +36,7 @@ AM_CPPFLAGS = # MPI bindings. if OMPI_BUILD_FORTRAN_USEMPIF08_BINDINGS -AM_FCFLAGS = -I$(top_srcdir)/ompi/mpi/fortran/use-mpi-f08/mod \ - -I$(top_builddir)/ompi/include \ +AM_FCFLAGS = -I$(top_builddir)/ompi/include \ -I$(top_srcdir)/ompi/include \ $(OMPI_FC_MODULE_FLAG)$(top_builddir)/ompi/mpi/fortran/use-mpi \ $(OMPI_FC_MODULE_FLAG)$(top_builddir)/ompi/$(OMPI_FORTRAN_USEMPI_DIR) \ @@ -541,6 +540,14 @@ lib@OMPI_LIBMPI_NAME@_usempif08_la_DEPENDENCIES = \ lib@OMPI_LIBMPI_NAME@_usempif08_profile.la lib@OMPI_LIBMPI_NAME@_usempif08_la_LDFLAGS = -version-info $(libmpi_usempif08_so_version) +if OMPI_FORTRAN_HAVE_TS +lib@OMPI_LIBMPI_NAME@_usempif08_la_LIBADD += \ + ts/libusempif08_ts.la + +lib@OMPI_LIBMPI_NAME@_usempif08_la_DEPENDENCIES += \ + ts/libusempif08_ts.la +endif + # # Automake doesn't do Fortran dependency analysis, so must list them # manually here. Bummer! diff --git a/ompi/mpi/fortran/use-mpi-f08/ts/bindings.h b/ompi/mpi/fortran/use-mpi-f08/ts/bindings.h index cb113f9d2ba..000192a5c11 100644 --- a/ompi/mpi/fortran/use-mpi-f08/ts/bindings.h +++ b/ompi/mpi/fortran/use-mpi-f08/ts/bindings.h @@ -103,7 +103,6 @@ void ompi_ssend_init_ts(CFI_cdesc_t* x, MPI_Fint *count, MPI_Fint *datatype, void ompi_get_address_ts(CFI_cdesc_t *x, MPI_Aint *address, MPI_Fint *ierr); -<<<<<<< HEAD void ompi_pack_ts(CFI_cdesc_t* x1, MPI_Fint *incount, MPI_Fint *datatype, CFI_cdesc_t* x2, MPI_Fint *outsize, MPI_Fint *position, MPI_Fint *comm, MPI_Fint *ierr); diff --git a/ompi/mpi/fortran/use-mpi-f08/ts/ts.c b/ompi/mpi/fortran/use-mpi-f08/ts/ts.c new file mode 100644 index 00000000000..0749c5681c3 --- /dev/null +++ b/ompi/mpi/fortran/use-mpi-f08/ts/ts.c @@ -0,0 +1,94 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * Copyright (c) 2014 Argonne National Laboratory. + * Copyright (c) 2019 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "ts.h" + +#include + +int ompi_ts_create_datatype(CFI_cdesc_t *cdesc, int oldcount, MPI_Datatype oldtype, MPI_Datatype *newtype) +{ + const int MAX_RANK = 15; /* Fortran 2008 specifies a maximum rank of 15 */ + MPI_Datatype types[MAX_RANK + 1]; /* Use a fixed size array to avoid malloc. + 1 for oldtype */ + int mpi_errno = MPI_SUCCESS; + int accum_elems = 1; + int accum_sm = cdesc->elem_len; + int done = 0; /* Have we created a datatype for oldcount of oldtype? */ + int last; /* Index of the last successfully created datatype in types[] */ + int extent; + int i, j; + +#ifdef OPAL_ENABLE_DEBUG + { + size_t size; + assert(cdesc->rank <= MAX_RANK); + ompi_datatype_type_size(oldtype, &size); + /* When cdesc->elem_len != size, things suddenly become complicated. Generally, it is hard to create + * a composite datatype based on two datatypes. Currently we don't support it and doubt it is usefull. + */ + assert(cdesc->elem_len == size); + } +#endif + + types[0] = oldtype; + i = 0; + done = 0; + while (i < cdesc->rank && !done) { + if (oldcount % accum_elems) { + /* oldcount should be a multiple of accum_elems, otherwise we might need an + * MPI indexed datatype to describle the irregular region, which is not supported yet. + */ + mpi_errno = MPI_ERR_INTERN; + last = i; + goto fn_exit; + } + + extent = oldcount / accum_elems; + if (extent > cdesc->dim[i].extent) { + extent = cdesc->dim[i].extent; + } else { + /* Up to now, we have accumlated enough elements */ + done = 1; + } + + if (cdesc->dim[i].sm == accum_sm) { + mpi_errno = PMPI_Type_contiguous(extent, types[i], &types[i+1]); + } else { + mpi_errno = PMPI_Type_create_hvector(extent, 1, cdesc->dim[i].sm, types[i], &types[i+1]); + } + if (mpi_errno != MPI_SUCCESS) { + last = i; + goto fn_exit; + } + + accum_sm = cdesc->dim[i].sm * cdesc->dim[i].extent; + accum_elems *= cdesc->dim[i].extent; + i++; + } + + if (done) { + *newtype = types[i]; + MPI_Type_commit(newtype); + last = i - 1; /* To avoid freeing newtype */ + } else { + /* If # of elements given by "oldcount oldtype" is bigger than + * what cdesc describles, then we will reach here. + */ + last = i; + mpi_errno = MPI_ERR_ARG; + goto fn_exit; + } + +fn_exit: + for (j = 1; j <= last; j++) + PMPI_Type_free(&types[j]); + return mpi_errno; +} diff --git a/ompi/mpi/fortran/use-mpi-f08/ts/ts.h b/ompi/mpi/fortran/use-mpi-f08/ts/ts.h new file mode 100644 index 00000000000..5e3af8b3fde --- /dev/null +++ b/ompi/mpi/fortran/use-mpi-f08/ts/ts.h @@ -0,0 +1,48 @@ +/* -*- Mode: C; c-basic-offset:4 ; -*- */ +/* + * Copyright (c) 2014 Argonne National Laboratory. + * Copyright (c) 2019 Research Organization for Information Science + * and Technology (RIST). All rights reserved. + * $COPYRIGHT$ + * + * Additional copyrights may follow + * + * $HEADER$ + */ + +#include "ompi_config.h" + +#include + +#include "ompi/datatype/ompi_datatype.h" +#include "ompi/mpi/fortran/base/fint_2_int.h" + +extern int ompi_ts_create_datatype(CFI_cdesc_t *cdesc, int oldcount, MPI_Datatype oldtype, MPI_Datatype *newtype); + +#define OMPI_CFI_2_C(x, count, type, datatype, rc) \ + do { \ + datatype = type; \ + if (x->rank != 0 && !CFI_is_contiguous(x)) { \ + rc = ompi_ts_create_datatype(x, count, type, &datatype); \ + if (MPI_SUCCESS != rc) { \ + return; \ + } else { \ + count = 1; \ + } \ + } else { \ + rc = MPI_SUCCESS; \ + } \ + } while (0) + +#define OMPI_CFI_IS_CONTIGUOUS(x) \ + (0 == x->rank || CFI_is_contiguous(x)) + +#define OMPI_CFI_CHECK_CONTIGUOUS(x, rc) \ + do { \ + if (OMPI_CFI_IS_CONTIGUOUS(x)) { \ + rc = MPI_SUCCESS; \ + } else { \ + rc = MPI_ERR_INTERN; \ + } \ + } while (0) +