Skip to content

Commit ae8adf3

Browse files
committed
Refactor bigcount/ABI generation code and add Fortran TS 29113 support
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 <jtronge@lanl.gov>
1 parent 37ada30 commit ae8adf3

28 files changed

+3261
-2349
lines changed

.gitignore

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -531,9 +531,10 @@ docs/_static
531531
docs/_static/css/custom.css
532532
docs/_templates
533533

534-
# Common Python virtual environment directory names
534+
# Common Python virtual environment and cache directory names
535535
venv
536536
py??
537+
__pycache__/
537538

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

548+
# Generated binding scripts
549+
ompi/mpi/bindings/ompi_bindings/compiler.py
550+
547551
# Generated C Bindings
548552
ompi/mpi/c/ompi_*.c
549553

550554
# Generated Fortran Bindings
551555
ompi/mpi/fortran/use-mpi-f08/*_generated.F90
552556
ompi/mpi/fortran/use-mpi-f08/base/*_generated.c
553-
ompi/mpi/fortran/use-mpi-f08/generate_bindings.py
557+
ompi/mpi/fortran/use-mpi-f08/mod/mpi-f08-interfaces-generated.h

config/ompi_config_files.m4

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ AC_DEFUN([OMPI_CONFIG_FILES],[
4444
ompi/mpi/fortran/use-mpi-f08/bindings/Makefile
4545
ompi/mpi/fortran/use-mpi-f08/mod/Makefile
4646
ompi/mpi/fortran/use-mpi-f08/mod/mpi-f08-interfaces.h
47-
ompi/mpi/fortran/use-mpi-f08/generate_bindings.py
4847
ompi/mpi/fortran/mpiext-use-mpi/Makefile
4948
ompi/mpi/fortran/mpiext-use-mpi-f08/Makefile
49+
ompi/mpi/bindings/ompi_bindings/compiler.py
5050
ompi/mpi/tool/Makefile
5151

5252
ompi/tools/ompi_info/Makefile

config/ompi_fortran_check_ts.m4

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
dnl -*- shell-script -*-
2+
dnl
3+
dnl Copyright (c) 2019 Research Organization for Information Science
4+
dnl and Technology (RIST). All rights reserved.
5+
dnl $COPYRIGHT$
6+
dnl
7+
dnl Additional copyrights may follow
8+
dnl
9+
dnl $HEADER$
10+
dnl
11+
12+
# Check whether or not the C compiler supports ISO_Fortran_binding.h
13+
# Also check whether C and Fortran compiler interoperate.
14+
#
15+
# OMPI_FORTRAN_CHECK_TS([action if found], [action if not found])
16+
# ----------------------------------------------------
17+
AC_DEFUN([OMPI_FORTRAN_CHECK_TS],[
18+
AS_VAR_PUSHDEF([fortran_ts], [ompi_cv_fortran_have_ts])
19+
20+
AC_CHECK_HEADERS([ISO_Fortran_binding.h],
21+
[AC_CACHE_CHECK([if Fortran and C compilers support ISO_Fortran_binding.h], fortran_ts,
22+
[mkdir conftest.$$
23+
cd conftest.$$
24+
25+
# Try to compile the C bindings
26+
cat > conftest_c.c << EOF
27+
#include <ISO_Fortran_binding.h>
28+
29+
int is_contiguous_c(CFI_cdesc_t* x) {
30+
return CFI_is_contiguous(x);
31+
}
32+
EOF
33+
OPAL_LOG_COMMAND([$CC $CCFLAGS -c conftest_c.c],
34+
[cat > conftest.f90 << EOF
35+
module MOD_IS_CONTIGUOUS
36+
37+
interface
38+
39+
function is_contiguous(buf) BIND(C, name="is_contiguous_c")
40+
implicit none
41+
type(*), dimension(..) :: buf
42+
integer :: is_contiguous
43+
end function is_contiguous
44+
45+
end interface
46+
47+
end module
48+
49+
program test_is_contiguous
50+
use MOD_IS_CONTIGUOUS
51+
implicit none
52+
integer :: a0, a1(2), a2(2,2), a3(2,2,2)
53+
write (*,*) is_contiguous(a0)
54+
write (*,*) is_contiguous(a1)
55+
write (*,*) is_contiguous(a2)
56+
write (*,*) is_contiguous(a3)
57+
end program
58+
EOF
59+
OPAL_LOG_COMMAND([$FC $FCFLAGS $FCFLAGS_f90 -o conftest conftest.f90 conftest_c.o $LDFLAGS $LIBS],
60+
[AS_VAR_SET(fortran_ts, yes)],
61+
[AS_VAR_SET(fortran_ts, no)])],
62+
[AS_VAR_SET(fortran_ts, no)])
63+
cd ..
64+
rm -rf conftest.$$])],
65+
[AS_VAR_SET(fortran_ts, no)])
66+
67+
AS_VAR_IF(fortran_ts, [yes], [$1], [$2])
68+
AS_VAR_POPDEF([fortran_ts])dnl
69+
])

config/ompi_setup_mpi_fortran.m4

Lines changed: 47 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -449,14 +449,27 @@ end program]])],
449449
# If we got all the stuff from above, then also look for the new
450450
# F08 syntax that we can use for the use_mpif08 module.
451451

452-
# We need to have ignore TKR functionality to build the mpi_f08
452+
OMPI_FORTRAN_HAVE_TS=0
453+
OMPI_MPI_SUBARRAYS_SUPPORTED=.false.
454+
OMPI_MPI_ASYNC_PROTECTS_NONBLOCKING=.false.
455+
AS_IF([test $OMPI_TRY_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS],
456+
[OMPI_FORTRAN_CHECK_TS([OMPI_FORTRAN_HAVE_TS=1])])
457+
458+
AC_SUBST(OMPI_MPI_SUBARRAYS_SUPPORTED)
459+
AC_SUBST(OMPI_MPI_ASYNC_PROTECTS_NONBLOCKING)
460+
461+
# We need to have ignore TKR or the ISO Fortran bindings functionality to build the mpi_f08
453462
# module
454-
AS_IF([test $OMPI_TRY_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS && \
455-
test $OMPI_FORTRAN_HAVE_IGNORE_TKR -eq 1],
456-
[OMPI_BUILD_FORTRAN_BINDINGS=$OMPI_FORTRAN_USEMPIF08_BINDINGS
457-
OMPI_FORTRAN_F08_PREDECL=$OMPI_FORTRAN_IGNORE_TKR_PREDECL
458-
OMPI_FORTRAN_F08_TYPE=$OMPI_FORTRAN_IGNORE_TKR_TYPE
459-
])
463+
AS_IF([test $OMPI_TRY_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS],
464+
[AS_IF([test $OMPI_FORTRAN_HAVE_IGNORE_TKR -eq 1],
465+
[OMPI_BUILD_FORTRAN_BINDINGS=$OMPI_FORTRAN_USEMPIF08_BINDINGS
466+
OMPI_FORTRAN_F08_PREDECL=$OMPI_FORTRAN_IGNORE_TKR_PREDECL
467+
OMPI_FORTRAN_F08_TYPE=$OMPI_FORTRAN_IGNORE_TKR_TYPE
468+
])
469+
AS_IF([test $OMPI_FORTRAN_HAVE_TS -eq 1],
470+
[OMPI_BUILD_FORTRAN_BINDINGS=$OMPI_FORTRAN_USEMPIF08_BINDINGS
471+
OMPI_MPI_SUBARRAYS_SUPPORTED=.true.
472+
OMPI_MPI_ASYNC_PROTECTS_NONBLOCKING=.true.])])
460473

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

592605
OMPI_FORTRAN_NEED_WRAPPER_ROUTINES=1
593-
OMPI_FORTRAN_F08_PREDECL='!'
594-
OMPI_FORTRAN_F08_TYPE=real
595606
OMPI_FORTRAN_HAVE_F08_ASSUMED_RANK=0
596607
AS_IF([test $OMPI_TRY_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS && \
597608
test $OMPI_BUILD_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS],
598609
[ # Look for Fortran 2008 assumed rank syntax
599610
OMPI_FORTRAN_CHECK_F08_ASSUMED_RANK(
600611
[ # If we have assumed rank, we can build the use
601612
# mpi_f08 module "better"
602-
OMPI_FORTRAN_F08_PREDECL='!'
603-
OMPI_FORTRAN_F08_TYPE='type(*), dimension(..)'
604613
OMPI_FORTRAN_HAVE_F08_ASSUMED_RANK=1])
605614

606615
# Which mpi_f08 implementation are we using?
@@ -630,6 +639,12 @@ end type test_mpi_handle],
630639
[OMPI_FORTRAN_ELEMENTAL_TYPE=])])
631640
AC_SUBST(OMPI_FORTRAN_ELEMENTAL_TYPE)
632641

642+
OMPI_FORTRAN_HAVE_C_ISO_FORTRAN=0
643+
AS_IF([test $OMPI_TRY_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS && \
644+
test $OMPI_BUILD_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS],
645+
[OMPI_FORTRAN_CHECK_TS([OMPI_FORTRAN_HAVE_TS=1],
646+
[OMPI_FORTRAN_HAVE_TS=0])])
647+
633648
# Note: the current implementation *only* has wrappers;
634649
# there is no optimized implementation for a "good"
635650
# compiler. I'm leaving the above logic in place for
@@ -652,6 +667,8 @@ end type test_mpi_handle],
652667
AS_IF([test $OMPI_MIN_REQUIRED_FORTRAN_BINDINGS -gt $OMPI_BUILD_FORTRAN_BINDINGS],
653668
[AC_MSG_ERROR([Cannot build requested Fortran bindings, aborting])])
654669

670+
dnl AC_CONFIG_FILES([ompi/mpi/fortran/use-mpi-f08/bindings/mpi-f-interfaces-bind.h])
671+
655672
# -------------------
656673
# mpif.h final setup
657674
# -------------------
@@ -792,10 +809,9 @@ end type test_mpi_handle],
792809
# This goes into mpifort-wrapper-data.txt
793810
AC_SUBST(OMPI_FORTRAN_USEMPIF08_LIB)
794811

795-
# These go into interfaces/mpi-f08-interfaces-[no]bind.h (and
796-
# mpi-f*-interfaces*.h files)
797-
AC_SUBST(OMPI_FORTRAN_F08_PREDECL)
798-
AC_SUBST(OMPI_FORTRAN_F08_TYPE)
812+
# These go into mod/mpi-f08-interfaces.h
813+
AC_SUBST(OMPI_F08_IGNORE_TKR_PREDECL)
814+
AC_SUBST(OMPI_F08_IGNORE_TKR_TYPE)
799815

800816
AC_SUBST(OMPI_MPI_PREFIX)
801817
AC_SUBST(OMPI_MPI_BIND_PREFIX)
@@ -877,6 +893,22 @@ end type test_mpi_handle],
877893
# For configure-fortran-output.h
878894
AC_SUBST(OMPI_FORTRAN_HAVE_BIND_C)
879895

896+
AM_CONDITIONAL(OMPI_FORTRAN_HAVE_TS,
897+
[test $OMPI_FORTRAN_HAVE_TS -eq 1])
898+
AC_SUBST(OMPI_FORTRAN_HAVE_TS)
899+
900+
AS_IF([test $OMPI_FORTRAN_HAVE_TS -eq 1],
901+
[OMPI_F08_IGNORE_TKR_TYPE="type(*), dimension(..)"
902+
OMPI_F08_IGNORE_TKR_PREDECL="! no attribute required for"
903+
OMPI_F08_BINDINGS_EXTENSION="ts"
904+
OMPI_F08_BINDINGS_TS_SUFFIX="ts"],
905+
[OMPI_F08_IGNORE_TKR_TYPE=$OMPI_FORTRAN_IGNORE_TKR_TYPE
906+
OMPI_F08_IGNORE_TKR_PREDECL=$OMPI_FORTRAN_IGNORE_TKR_PREDECL
907+
OMPI_F08_BINDINGS_EXTENSION="f"
908+
OMPI_F08_BINDINGS_TS_SUFFIX=""])
909+
AC_SUBST(OMPI_F08_BINDINGS_EXTENSION)
910+
AC_SUBST(OMPI_F08_BINDINGS_TS_SUFFIX)
911+
880912
# Somewhat redundant because ompi/Makefile.am won't traverse into
881913
# ompi/mpi/fortran/use-mpi-f08 if it's not to be built, but we
882914
# might as well have ompi/mpi/fortran/use-mpi-f08/Makefile.am be

ompi/include/mpi.h.in

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,6 +1437,9 @@ OMPI_DECLSPEC int MPI_Alltoall_init(const void *sendbuf, int sendcount, MPI_Dat
14371437
OMPI_DECLSPEC int MPI_Alltoallv(const void *sendbuf, const int sendcounts[], const int sdispls[], MPI_Datatype sendtype,
14381438
void *recvbuf, const int recvcounts[], const int rdispls[], MPI_Datatype recvtype,
14391439
MPI_Comm comm);
1440+
OMPI_DECLSPEC int MPI_Alltoallv_c(const void *sendbuf, const MPI_Count sendcounts[], const MPI_Aint sdispls[], MPI_Datatype sendtype,
1441+
void *recvbuf, const MPI_Count recvcounts[], const MPI_Aint rdispls[], MPI_Datatype recvtype,
1442+
MPI_Comm comm);
14401443
OMPI_DECLSPEC int MPI_Ialltoallv(const void *sendbuf, const int sendcounts[], const int sdispls[], MPI_Datatype sendtype,
14411444
void *recvbuf, const int recvcounts[], const int rdispls[], MPI_Datatype recvtype,
14421445
MPI_Comm comm, MPI_Request *request);
@@ -1446,6 +1449,9 @@ OMPI_DECLSPEC int MPI_Alltoallv_init(const void *sendbuf, const int sendcounts[
14461449
OMPI_DECLSPEC int MPI_Alltoallw(const void *sendbuf, const int sendcounts[], const int sdispls[], const MPI_Datatype sendtypes[],
14471450
void *recvbuf, const int recvcounts[], const int rdispls[], const MPI_Datatype recvtypes[],
14481451
MPI_Comm comm);
1452+
OMPI_DECLSPEC int MPI_Alltoallw_c(const void *sendbuf, const MPI_Count sendcounts[], const MPI_Aint sdispls[], const MPI_Datatype sendtypes[],
1453+
void *recvbuf, const MPI_Count recvcounts[], const MPI_Aint rdispls[], const MPI_Datatype recvtypes[],
1454+
MPI_Comm comm);
14491455
OMPI_DECLSPEC int MPI_Ialltoallw(const void *sendbuf, const int sendcounts[], const int sdispls[], const MPI_Datatype sendtypes[],
14501456
void *recvbuf, const int recvcounts[], const int rdispls[], const MPI_Datatype recvtypes[],
14511457
MPI_Comm comm, MPI_Request *request);
@@ -2209,6 +2215,9 @@ OMPI_DECLSPEC int PMPI_Alltoall_init(const void *sendbuf, int sendcount, MPI_Da
22092215
OMPI_DECLSPEC int PMPI_Alltoallv(const void *sendbuf, const int sendcounts[], const int sdispls[], MPI_Datatype sendtype,
22102216
void *recvbuf, const int recvcounts[], const int rdispls[], MPI_Datatype recvtype,
22112217
MPI_Comm comm);
2218+
OMPI_DECLSPEC int PMPI_Alltoallv_c(const void *sendbuf, const MPI_Count sendcounts[], const MPI_Aint sdispls[], MPI_Datatype sendtype,
2219+
void *recvbuf, const MPI_Count recvcounts[], const MPI_Aint rdispls[], MPI_Datatype recvtype,
2220+
MPI_Comm comm);
22122221
OMPI_DECLSPEC int PMPI_Ialltoallv(const void *sendbuf, const int sendcounts[], const int sdispls[], MPI_Datatype sendtype,
22132222
void *recvbuf, const int recvcounts[], const int rdispls[], MPI_Datatype recvtype,
22142223
MPI_Comm comm, MPI_Request *request);
@@ -2218,6 +2227,9 @@ OMPI_DECLSPEC int PMPI_Alltoallv_init(const void *sendbuf, const int sendcounts
22182227
OMPI_DECLSPEC int PMPI_Alltoallw(const void *sendbuf, const int sendcounts[], const int sdispls[], const MPI_Datatype sendtypes[],
22192228
void *recvbuf, const int recvcounts[], const int rdispls[], const MPI_Datatype recvtypes[],
22202229
MPI_Comm comm);
2230+
OMPI_DECLSPEC int PMPI_Alltoallw_c(const void *sendbuf, const MPI_Count sendcounts[], const MPI_Aint sdispls[], const MPI_Datatype sendtypes[],
2231+
void *recvbuf, const MPI_Count recvcounts[], const MPI_Aint rdispls[], const MPI_Datatype recvtypes[],
2232+
MPI_Comm comm);
22212233
OMPI_DECLSPEC int PMPI_Ialltoallw(const void *sendbuf, const int sendcounts[], const int sdispls[], const MPI_Datatype sendtypes[],
22222234
void *recvbuf, const int recvcounts[], const int rdispls[], const MPI_Datatype recvtypes[],
22232235
MPI_Comm comm, MPI_Request *request);

ompi/mpi/bindings/bindings.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Copyright (c) 2024 Triad National Security, LLC. All rights
2+
# reserved.
3+
#
4+
# $COPYRIGHT$
5+
#
6+
# Additional copyrights may follow
7+
#
8+
# $HEADER$
9+
import argparse
10+
import os
11+
import sys
12+
13+
14+
def handle_missing_command(args, out):
15+
print('missing subcommand (one of {fortran,c} required)', file=sys.stderr)
16+
sys.exit(1)
17+
18+
19+
def main():
20+
parser = argparse.ArgumentParser(description='generate fortran binding files')
21+
parser.add_argument('--builddir', required=True, help='absolute path to automake builddir (abs_top_builddir)')
22+
parser.add_argument('--output', required=True, help='output file to use')
23+
parser.add_argument('--srcdir', required=True, help='absolute path to automake srcdir (abs_top_srcdir)')
24+
parser.set_defaults(handler=handle_missing_command)
25+
subparsers = parser.add_subparsers()
26+
27+
# Fortran set up code
28+
parser_fortran = subparsers.add_parser('fortran', help='subcommand for generating Fortran code')
29+
parser_fortran.add_argument('--template', required=True, help='template file to use')
30+
subparsers_fortran = parser_fortran.add_subparsers()
31+
# Handler for generating actual code
32+
parser_code = subparsers_fortran.add_parser('code', help='generate binding code')
33+
parser_code.add_argument('lang', choices=('fortran', 'c'),
34+
help='generate dependent files in C or Fortran')
35+
parser_code.set_defaults(handler=lambda args, out: fortran.generate_code(args, out))
36+
# Handler for generating the Fortran interface files
37+
parser_interface = subparsers_fortran.add_parser('interface',
38+
help='generate Fortran interface specifcations')
39+
parser_interface.set_defaults(handler=lambda args, out: fortran.generate_interface(args, out))
40+
41+
# C set up code
42+
parser_c = subparsers.add_parser('c', help='subcommand for generating C code')
43+
subparsers_c = parser_c.add_subparsers()
44+
parser_header = subparsers_c.add_parser('header')
45+
parser_header.add_argument('file', nargs='+', help='list of template source files')
46+
parser_header.add_argument('--external', action='store_true', help='generate external mpi.h header file')
47+
parser_header.add_argument('--srcdir', help='source directory')
48+
parser_header.set_defaults(handler=lambda args, out: c.generate_header(args, out))
49+
parser_gen = subparsers_c.add_parser('source')
50+
# parser = argparse.ArgumentParser(description='C ABI binding generation code')
51+
parser_gen.add_argument('type', choices=('ompi', 'standard'),
52+
help='generate the OMPI ABI functions or the standard ABI functions')
53+
parser_gen.add_argument('source_file', help='template file to use for C code generation')
54+
parser_gen.set_defaults(handler=lambda args, out: c.generate_source(args, out))
55+
args = parser.parse_args()
56+
57+
# Pull in both generated python files and src files on import
58+
sys.path.insert(0, os.path.join(args.builddir, 'ompi/mpi/bindings'))
59+
sys.path.insert(0, os.path.join(args.srcdir, 'ompi/mpi/bindings'))
60+
from ompi_bindings import c, fortran
61+
from ompi_bindings.util import OutputFile
62+
63+
with open(args.output, 'w') as f:
64+
args.handler(args, OutputFile(f))
65+
66+
67+
if __name__ == '__main__':
68+
main()

0 commit comments

Comments
 (0)