Skip to content

Commit

Permalink
Refactor bigcount/ABI generation code and add Fortran TS 29113 support
Browse files Browse the repository at this point in the history
This refactors the Python scripts for generating the C and Fortran
interfaces into ompi/mpi/bindings/ and extends the Fortran code for more
complicated functions.

TS 29113 support is also added here, with code imported from PR #10302.

Signed-off-by: Jake Tronge <[email protected]>
  • Loading branch information
jtronge committed Feb 7, 2024
1 parent 37ada30 commit ae8adf3
Show file tree
Hide file tree
Showing 28 changed files with 3,261 additions and 2,349 deletions.
8 changes: 6 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -531,9 +531,10 @@ docs/_static
docs/_static/css/custom.css
docs/_templates

# Common Python virtual environment directory names
# Common Python virtual environment and cache directory names
venv
py??
__pycache__/

# Copies of PRRTE RST files (i.e., not source controlled in this tree)
docs/prrte-rst-content
Expand All @@ -544,10 +545,13 @@ docs/schizo-ompi-rst-content
docs/html
docs/man

# Generated binding scripts
ompi/mpi/bindings/ompi_bindings/compiler.py

# Generated C Bindings
ompi/mpi/c/ompi_*.c

# Generated Fortran Bindings
ompi/mpi/fortran/use-mpi-f08/*_generated.F90
ompi/mpi/fortran/use-mpi-f08/base/*_generated.c
ompi/mpi/fortran/use-mpi-f08/generate_bindings.py
ompi/mpi/fortran/use-mpi-f08/mod/mpi-f08-interfaces-generated.h
2 changes: 1 addition & 1 deletion config/ompi_config_files.m4
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ AC_DEFUN([OMPI_CONFIG_FILES],[
ompi/mpi/fortran/use-mpi-f08/bindings/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/generate_bindings.py
ompi/mpi/fortran/mpiext-use-mpi/Makefile
ompi/mpi/fortran/mpiext-use-mpi-f08/Makefile
ompi/mpi/bindings/ompi_bindings/compiler.py
ompi/mpi/tool/Makefile

ompi/tools/ompi_info/Makefile
Expand Down
69 changes: 69 additions & 0 deletions config/ompi_fortran_check_ts.m4
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
dnl -*- shell-script -*-
dnl
dnl Copyright (c) 2019 Research Organization for Information Science
dnl and Technology (RIST). All rights reserved.
dnl $COPYRIGHT$
dnl
dnl Additional copyrights may follow
dnl
dnl $HEADER$
dnl

# Check whether or not the C compiler supports ISO_Fortran_binding.h
# Also check whether C and Fortran compiler interoperate.
#
# OMPI_FORTRAN_CHECK_TS([action if found], [action if not found])
# ----------------------------------------------------
AC_DEFUN([OMPI_FORTRAN_CHECK_TS],[
AS_VAR_PUSHDEF([fortran_ts], [ompi_cv_fortran_have_ts])

AC_CHECK_HEADERS([ISO_Fortran_binding.h],
[AC_CACHE_CHECK([if Fortran and C compilers support ISO_Fortran_binding.h], fortran_ts,
[mkdir conftest.$$
cd conftest.$$

# Try to compile the C bindings
cat > conftest_c.c << EOF
#include <ISO_Fortran_binding.h>

int is_contiguous_c(CFI_cdesc_t* x) {
return CFI_is_contiguous(x);
}
EOF
OPAL_LOG_COMMAND([$CC $CCFLAGS -c conftest_c.c],
[cat > conftest.f90 << EOF
module MOD_IS_CONTIGUOUS

interface

function is_contiguous(buf) BIND(C, name="is_contiguous_c")
implicit none
type(*), dimension(..) :: buf
integer :: is_contiguous
end function is_contiguous

end interface

end module

program test_is_contiguous
use MOD_IS_CONTIGUOUS
implicit none
integer :: a0, a1(2), a2(2,2), a3(2,2,2)
write (*,*) is_contiguous(a0)
write (*,*) is_contiguous(a1)
write (*,*) is_contiguous(a2)
write (*,*) is_contiguous(a3)
end program
EOF
OPAL_LOG_COMMAND([$FC $FCFLAGS $FCFLAGS_f90 -o conftest conftest.f90 conftest_c.o $LDFLAGS $LIBS],
[AS_VAR_SET(fortran_ts, yes)],
[AS_VAR_SET(fortran_ts, no)])],
[AS_VAR_SET(fortran_ts, no)])
cd ..
rm -rf conftest.$$])],
[AS_VAR_SET(fortran_ts, no)])

AS_VAR_IF(fortran_ts, [yes], [$1], [$2])
AS_VAR_POPDEF([fortran_ts])dnl
])
62 changes: 47 additions & 15 deletions config/ompi_setup_mpi_fortran.m4
Original file line number Diff line number Diff line change
Expand Up @@ -449,14 +449,27 @@ end program]])],
# If we got all the stuff from above, then also look for the new
# F08 syntax that we can use for the use_mpif08 module.

# We need to have ignore TKR functionality to build the mpi_f08
OMPI_FORTRAN_HAVE_TS=0
OMPI_MPI_SUBARRAYS_SUPPORTED=.false.
OMPI_MPI_ASYNC_PROTECTS_NONBLOCKING=.false.
AS_IF([test $OMPI_TRY_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS],
[OMPI_FORTRAN_CHECK_TS([OMPI_FORTRAN_HAVE_TS=1])])

AC_SUBST(OMPI_MPI_SUBARRAYS_SUPPORTED)
AC_SUBST(OMPI_MPI_ASYNC_PROTECTS_NONBLOCKING)

# 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 && \
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_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.])])

# The overall "_BIND_C" variable will be set to 1 if we have all
# the necessary forms of BIND(C)
Expand Down Expand Up @@ -590,17 +603,13 @@ end type test_mpi_handle],
])

OMPI_FORTRAN_NEED_WRAPPER_ROUTINES=1
OMPI_FORTRAN_F08_PREDECL='!'
OMPI_FORTRAN_F08_TYPE=real
OMPI_FORTRAN_HAVE_F08_ASSUMED_RANK=0
AS_IF([test $OMPI_TRY_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS && \
test $OMPI_BUILD_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS],
[ # Look for Fortran 2008 assumed rank syntax
OMPI_FORTRAN_CHECK_F08_ASSUMED_RANK(
[ # If we have assumed rank, we can build the use
# mpi_f08 module "better"
OMPI_FORTRAN_F08_PREDECL='!'
OMPI_FORTRAN_F08_TYPE='type(*), dimension(..)'
OMPI_FORTRAN_HAVE_F08_ASSUMED_RANK=1])

# Which mpi_f08 implementation are we using?
Expand Down Expand Up @@ -630,6 +639,12 @@ end type test_mpi_handle],
[OMPI_FORTRAN_ELEMENTAL_TYPE=])])
AC_SUBST(OMPI_FORTRAN_ELEMENTAL_TYPE)

OMPI_FORTRAN_HAVE_C_ISO_FORTRAN=0
AS_IF([test $OMPI_TRY_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS && \
test $OMPI_BUILD_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS],
[OMPI_FORTRAN_CHECK_TS([OMPI_FORTRAN_HAVE_TS=1],
[OMPI_FORTRAN_HAVE_TS=0])])

# Note: the current implementation *only* has wrappers;
# there is no optimized implementation for a "good"
# compiler. I'm leaving the above logic in place for
Expand All @@ -652,6 +667,8 @@ 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])

# -------------------
# mpif.h final setup
# -------------------
Expand Down Expand Up @@ -792,10 +809,9 @@ end type test_mpi_handle],
# This goes into mpifort-wrapper-data.txt
AC_SUBST(OMPI_FORTRAN_USEMPIF08_LIB)

# These go into interfaces/mpi-f08-interfaces-[no]bind.h (and
# mpi-f*-interfaces*.h files)
AC_SUBST(OMPI_FORTRAN_F08_PREDECL)
AC_SUBST(OMPI_FORTRAN_F08_TYPE)
# These go into mod/mpi-f08-interfaces.h
AC_SUBST(OMPI_F08_IGNORE_TKR_PREDECL)
AC_SUBST(OMPI_F08_IGNORE_TKR_TYPE)

AC_SUBST(OMPI_MPI_PREFIX)
AC_SUBST(OMPI_MPI_BIND_PREFIX)
Expand Down Expand Up @@ -877,6 +893,22 @@ end type test_mpi_handle],
# For configure-fortran-output.h
AC_SUBST(OMPI_FORTRAN_HAVE_BIND_C)

AM_CONDITIONAL(OMPI_FORTRAN_HAVE_TS,
[test $OMPI_FORTRAN_HAVE_TS -eq 1])
AC_SUBST(OMPI_FORTRAN_HAVE_TS)

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_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
OMPI_F08_BINDINGS_EXTENSION="f"
OMPI_F08_BINDINGS_TS_SUFFIX=""])
AC_SUBST(OMPI_F08_BINDINGS_EXTENSION)
AC_SUBST(OMPI_F08_BINDINGS_TS_SUFFIX)

# Somewhat redundant because ompi/Makefile.am won't traverse into
# ompi/mpi/fortran/use-mpi-f08 if it's not to be built, but we
# might as well have ompi/mpi/fortran/use-mpi-f08/Makefile.am be
Expand Down
12 changes: 12 additions & 0 deletions ompi/include/mpi.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -1437,6 +1437,9 @@ OMPI_DECLSPEC int MPI_Alltoall_init(const void *sendbuf, int sendcount, MPI_Dat
OMPI_DECLSPEC int MPI_Alltoallv(const void *sendbuf, const int sendcounts[], const int sdispls[], MPI_Datatype sendtype,
void *recvbuf, const int recvcounts[], const int rdispls[], MPI_Datatype recvtype,
MPI_Comm comm);
OMPI_DECLSPEC int MPI_Alltoallv_c(const void *sendbuf, const MPI_Count sendcounts[], const MPI_Aint sdispls[], MPI_Datatype sendtype,
void *recvbuf, const MPI_Count recvcounts[], const MPI_Aint rdispls[], MPI_Datatype recvtype,
MPI_Comm comm);
OMPI_DECLSPEC int MPI_Ialltoallv(const void *sendbuf, const int sendcounts[], const int sdispls[], MPI_Datatype sendtype,
void *recvbuf, const int recvcounts[], const int rdispls[], MPI_Datatype recvtype,
MPI_Comm comm, MPI_Request *request);
Expand All @@ -1446,6 +1449,9 @@ OMPI_DECLSPEC int MPI_Alltoallv_init(const void *sendbuf, const int sendcounts[
OMPI_DECLSPEC int MPI_Alltoallw(const void *sendbuf, const int sendcounts[], const int sdispls[], const MPI_Datatype sendtypes[],
void *recvbuf, const int recvcounts[], const int rdispls[], const MPI_Datatype recvtypes[],
MPI_Comm comm);
OMPI_DECLSPEC int MPI_Alltoallw_c(const void *sendbuf, const MPI_Count sendcounts[], const MPI_Aint sdispls[], const MPI_Datatype sendtypes[],
void *recvbuf, const MPI_Count recvcounts[], const MPI_Aint rdispls[], const MPI_Datatype recvtypes[],
MPI_Comm comm);
OMPI_DECLSPEC int MPI_Ialltoallw(const void *sendbuf, const int sendcounts[], const int sdispls[], const MPI_Datatype sendtypes[],
void *recvbuf, const int recvcounts[], const int rdispls[], const MPI_Datatype recvtypes[],
MPI_Comm comm, MPI_Request *request);
Expand Down Expand Up @@ -2209,6 +2215,9 @@ OMPI_DECLSPEC int PMPI_Alltoall_init(const void *sendbuf, int sendcount, MPI_Da
OMPI_DECLSPEC int PMPI_Alltoallv(const void *sendbuf, const int sendcounts[], const int sdispls[], MPI_Datatype sendtype,
void *recvbuf, const int recvcounts[], const int rdispls[], MPI_Datatype recvtype,
MPI_Comm comm);
OMPI_DECLSPEC int PMPI_Alltoallv_c(const void *sendbuf, const MPI_Count sendcounts[], const MPI_Aint sdispls[], MPI_Datatype sendtype,
void *recvbuf, const MPI_Count recvcounts[], const MPI_Aint rdispls[], MPI_Datatype recvtype,
MPI_Comm comm);
OMPI_DECLSPEC int PMPI_Ialltoallv(const void *sendbuf, const int sendcounts[], const int sdispls[], MPI_Datatype sendtype,
void *recvbuf, const int recvcounts[], const int rdispls[], MPI_Datatype recvtype,
MPI_Comm comm, MPI_Request *request);
Expand All @@ -2218,6 +2227,9 @@ OMPI_DECLSPEC int PMPI_Alltoallv_init(const void *sendbuf, const int sendcounts
OMPI_DECLSPEC int PMPI_Alltoallw(const void *sendbuf, const int sendcounts[], const int sdispls[], const MPI_Datatype sendtypes[],
void *recvbuf, const int recvcounts[], const int rdispls[], const MPI_Datatype recvtypes[],
MPI_Comm comm);
OMPI_DECLSPEC int PMPI_Alltoallw_c(const void *sendbuf, const MPI_Count sendcounts[], const MPI_Aint sdispls[], const MPI_Datatype sendtypes[],
void *recvbuf, const MPI_Count recvcounts[], const MPI_Aint rdispls[], const MPI_Datatype recvtypes[],
MPI_Comm comm);
OMPI_DECLSPEC int PMPI_Ialltoallw(const void *sendbuf, const int sendcounts[], const int sdispls[], const MPI_Datatype sendtypes[],
void *recvbuf, const int recvcounts[], const int rdispls[], const MPI_Datatype recvtypes[],
MPI_Comm comm, MPI_Request *request);
Expand Down
68 changes: 68 additions & 0 deletions ompi/mpi/bindings/bindings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
# Copyright (c) 2024 Triad National Security, LLC. All rights
# reserved.
#
# $COPYRIGHT$
#
# Additional copyrights may follow
#
# $HEADER$
import argparse
import os
import sys


def handle_missing_command(args, out):
print('missing subcommand (one of {fortran,c} required)', file=sys.stderr)
sys.exit(1)


def main():
parser = argparse.ArgumentParser(description='generate fortran binding files')
parser.add_argument('--builddir', required=True, help='absolute path to automake builddir (abs_top_builddir)')
parser.add_argument('--output', required=True, help='output file to use')
parser.add_argument('--srcdir', required=True, help='absolute path to automake srcdir (abs_top_srcdir)')
parser.set_defaults(handler=handle_missing_command)
subparsers = parser.add_subparsers()

# Fortran set up code
parser_fortran = subparsers.add_parser('fortran', help='subcommand for generating Fortran code')
parser_fortran.add_argument('--template', required=True, help='template file to use')
subparsers_fortran = parser_fortran.add_subparsers()
# Handler for generating actual code
parser_code = subparsers_fortran.add_parser('code', help='generate binding code')
parser_code.add_argument('lang', choices=('fortran', 'c'),
help='generate dependent files in C or Fortran')
parser_code.set_defaults(handler=lambda args, out: fortran.generate_code(args, out))
# Handler for generating the Fortran interface files
parser_interface = subparsers_fortran.add_parser('interface',
help='generate Fortran interface specifcations')
parser_interface.set_defaults(handler=lambda args, out: fortran.generate_interface(args, out))

# C set up code
parser_c = subparsers.add_parser('c', help='subcommand for generating C code')
subparsers_c = parser_c.add_subparsers()
parser_header = subparsers_c.add_parser('header')
parser_header.add_argument('file', nargs='+', help='list of template source files')
parser_header.add_argument('--external', action='store_true', help='generate external mpi.h header file')
parser_header.add_argument('--srcdir', help='source directory')
parser_header.set_defaults(handler=lambda args, out: c.generate_header(args, out))
parser_gen = subparsers_c.add_parser('source')
# parser = argparse.ArgumentParser(description='C ABI binding generation code')
parser_gen.add_argument('type', choices=('ompi', 'standard'),
help='generate the OMPI ABI functions or the standard ABI functions')
parser_gen.add_argument('source_file', help='template file to use for C code generation')
parser_gen.set_defaults(handler=lambda args, out: c.generate_source(args, out))
args = parser.parse_args()

# Pull in both generated python files and src files on import
sys.path.insert(0, os.path.join(args.builddir, 'ompi/mpi/bindings'))
sys.path.insert(0, os.path.join(args.srcdir, 'ompi/mpi/bindings'))
from ompi_bindings import c, fortran
from ompi_bindings.util import OutputFile

with open(args.output, 'w') as f:
args.handler(args, OutputFile(f))


if __name__ == '__main__':
main()
Loading

0 comments on commit ae8adf3

Please sign in to comment.