Skip to content

Commit 92e1378

Browse files
authored
Merge pull request #12226 from jtronge/bigcount
Generate bigcount interfaces for Fortran and C
2 parents 5ae1b96 + 05a5924 commit 92e1378

File tree

1,229 files changed

+53231
-48445
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,229 files changed

+53231
-48445
lines changed

.gitignore

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ ompi/mpi/fortran/mpiext/mpi-ext-module.F90
201201
ompi/mpi/fortran/mpiext/mpi-f08-ext-module.F90
202202
ompi/mpi/fortran/mpiext-use-mpi/mpi-ext-module.F90
203203
ompi/mpi/fortran/mpiext-use-mpi-f08/mpi-f08-ext-module.F90
204+
ompi/mpi/fortran/use-mpi-f08/psizeof_f08.f90
204205

205206
ompi/mpi/fortran/mpif-h/sizeof_f.f90
206207
ompi/mpi/fortran/mpif-h/profile/p*.c
@@ -516,9 +517,10 @@ docs/_static
516517
docs/_static/css/custom.css
517518
docs/_templates
518519

519-
# Common Python virtual environment directory names
520+
# Common Python virtual environment and cache directory names
520521
venv
521522
py??
523+
__pycache__/
522524

523525
# Copies of PRRTE RST files (i.e., not source controlled in this tree)
524526
docs/prrte-rst-content
@@ -528,3 +530,11 @@ docs/schizo-ompi-rst-content
528530
# tarballs)
529531
docs/html
530532
docs/man
533+
534+
# Generated C Bindings
535+
ompi/mpi/c/*_generated*.c
536+
537+
# Generated Fortran Bindings
538+
ompi/mpi/fortran/use-mpi-f08/*_generated.F90
539+
ompi/mpi/fortran/use-mpi-f08/base/*_generated.c
540+
ompi/mpi/fortran/use-mpi-f08/mod/mpi-f08-interfaces-generated.h

config/ompi_config_files.m4

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ AC_DEFUN([OMPI_CONFIG_FILES],[
3838
ompi/mpi/fortran/use-mpi-ignore-tkr/mpi-ignore-tkr-removed-interfaces.h
3939
ompi/mpi/fortran/use-mpi-f08/Makefile
4040
ompi/mpi/fortran/use-mpi-f08/base/Makefile
41-
ompi/mpi/fortran/use-mpi-f08/profile/Makefile
4241
ompi/mpi/fortran/use-mpi-f08/bindings/Makefile
4342
ompi/mpi/fortran/use-mpi-f08/mod/Makefile
4443
ompi/mpi/fortran/use-mpi-f08/mod/mpi-f08-interfaces.h

config/ompi_configure_options.m4

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,5 +253,12 @@ else
253253
fi
254254
AM_CONDITIONAL(OMPI_OMPIO_SUPPORT, test "$ompi_want_ompio" = "1")
255255

256+
# If the binding source files don't exist, then we need Python to generate them
257+
AM_PATH_PYTHON([3.6],,[:])
258+
binding_file="${srcdir}/ompi/mpi/c/ompi_send.c"
259+
AS_IF([! test -e "$binding_file" && test "$PYTHON" = ":"],
260+
[AC_MSG_ERROR([Open MPI requires Python >=3.6 for generating the bindings. Aborting])])
261+
AM_CONDITIONAL(OMPI_GENERATE_BINDINGS,[test "$PYTHON" != ":"])
262+
256263
])dnl
257264

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: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -435,14 +435,27 @@ end program]])],
435435
# If we got all the stuff from above, then also look for the new
436436
# F08 syntax that we can use for the use_mpif08 module.
437437

438-
# We need to have ignore TKR functionality to build the mpi_f08
438+
OMPI_FORTRAN_HAVE_TS=0
439+
OMPI_MPI_SUBARRAYS_SUPPORTED=.false.
440+
OMPI_MPI_ASYNC_PROTECTS_NONBLOCKING=.false.
441+
AS_IF([test $OMPI_TRY_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS],
442+
[OMPI_FORTRAN_CHECK_TS([OMPI_FORTRAN_HAVE_TS=1])])
443+
444+
# We need to have ignore TKR or the ISO Fortran bindings functionality to build the mpi_f08
439445
# module
440-
AS_IF([test $OMPI_TRY_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS && \
441-
test $OMPI_FORTRAN_HAVE_IGNORE_TKR -eq 1],
442-
[OMPI_BUILD_FORTRAN_BINDINGS=$OMPI_FORTRAN_USEMPIF08_BINDINGS
443-
OMPI_FORTRAN_F08_PREDECL=$OMPI_FORTRAN_IGNORE_TKR_PREDECL
444-
OMPI_FORTRAN_F08_TYPE=$OMPI_FORTRAN_IGNORE_TKR_TYPE
445-
])
446+
AS_IF([test $OMPI_TRY_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS],
447+
[AS_IF([test $OMPI_FORTRAN_HAVE_IGNORE_TKR -eq 1],
448+
[OMPI_BUILD_FORTRAN_BINDINGS=$OMPI_FORTRAN_USEMPIF08_BINDINGS
449+
OMPI_FORTRAN_F08_PREDECL=$OMPI_FORTRAN_IGNORE_TKR_PREDECL
450+
OMPI_FORTRAN_F08_TYPE=$OMPI_FORTRAN_IGNORE_TKR_TYPE
451+
])
452+
AS_IF([test $OMPI_FORTRAN_HAVE_TS -eq 1],
453+
[OMPI_BUILD_FORTRAN_BINDINGS=$OMPI_FORTRAN_USEMPIF08_BINDINGS
454+
OMPI_MPI_SUBARRAYS_SUPPORTED=.true.
455+
OMPI_MPI_ASYNC_PROTECTS_NONBLOCKING=.true.])])
456+
457+
AC_SUBST(OMPI_MPI_SUBARRAYS_SUPPORTED)
458+
AC_SUBST(OMPI_MPI_ASYNC_PROTECTS_NONBLOCKING)
446459

447460
# The overall "_BIND_C" variable will be set to 1 if we have all
448461
# the necessary forms of BIND(C)
@@ -576,17 +589,13 @@ end type test_mpi_handle],
576589
])
577590

578591
OMPI_FORTRAN_NEED_WRAPPER_ROUTINES=1
579-
OMPI_FORTRAN_F08_PREDECL='!'
580-
OMPI_FORTRAN_F08_TYPE=real
581592
OMPI_FORTRAN_HAVE_F08_ASSUMED_RANK=0
582593
AS_IF([test $OMPI_TRY_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS && \
583594
test $OMPI_BUILD_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS],
584595
[ # Look for Fortran 2008 assumed rank syntax
585596
OMPI_FORTRAN_CHECK_F08_ASSUMED_RANK(
586597
[ # If we have assumed rank, we can build the use
587598
# mpi_f08 module "better"
588-
OMPI_FORTRAN_F08_PREDECL='!'
589-
OMPI_FORTRAN_F08_TYPE='type(*), dimension(..)'
590599
OMPI_FORTRAN_HAVE_F08_ASSUMED_RANK=1])
591600

592601
# Which mpi_f08 implementation are we using?
@@ -616,6 +625,12 @@ end type test_mpi_handle],
616625
[OMPI_FORTRAN_ELEMENTAL_TYPE=])])
617626
AC_SUBST(OMPI_FORTRAN_ELEMENTAL_TYPE)
618627

628+
OMPI_FORTRAN_HAVE_C_ISO_FORTRAN=0
629+
AS_IF([test $OMPI_TRY_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS && \
630+
test $OMPI_BUILD_FORTRAN_BINDINGS -ge $OMPI_FORTRAN_USEMPIF08_BINDINGS],
631+
[OMPI_FORTRAN_CHECK_TS([OMPI_FORTRAN_HAVE_TS=1],
632+
[OMPI_FORTRAN_HAVE_TS=0])])
633+
619634
# Note: the current implementation *only* has wrappers;
620635
# there is no optimized implementation for a "good"
621636
# compiler. I'm leaving the above logic in place for
@@ -778,10 +793,9 @@ end type test_mpi_handle],
778793
# This goes into mpifort-wrapper-data.txt
779794
AC_SUBST(OMPI_FORTRAN_USEMPIF08_LIB)
780795

781-
# These go into interfaces/mpi-f08-interfaces-[no]bind.h (and
782-
# mpi-f*-interfaces*.h files)
783-
AC_SUBST(OMPI_FORTRAN_F08_PREDECL)
784-
AC_SUBST(OMPI_FORTRAN_F08_TYPE)
796+
# These go into mod/mpi-f08-interfaces.h
797+
AC_SUBST(OMPI_F08_IGNORE_TKR_PREDECL)
798+
AC_SUBST(OMPI_F08_IGNORE_TKR_TYPE)
785799

786800
AC_SUBST(OMPI_MPI_PREFIX)
787801
AC_SUBST(OMPI_MPI_BIND_PREFIX)
@@ -863,6 +877,25 @@ end type test_mpi_handle],
863877
# For configure-fortran-output.h
864878
AC_SUBST(OMPI_FORTRAN_HAVE_BIND_C)
865879

880+
AM_CONDITIONAL(OMPI_FORTRAN_HAVE_TS,
881+
[test $OMPI_FORTRAN_HAVE_TS -eq 1])
882+
AC_SUBST(OMPI_FORTRAN_HAVE_TS)
883+
AC_DEFINE_UNQUOTED([OMPI_FORTRAN_HAVE_TS],
884+
[$OMPI_FORTRAN_HAVE_TS],
885+
[For ompi/mpi/fortran/use-mpi-f08/base/ts.*: whether the compiler supports TS 29113 or not])
886+
887+
AS_IF([test $OMPI_FORTRAN_HAVE_TS -eq 1],
888+
[OMPI_F08_IGNORE_TKR_TYPE="type(*), dimension(..)"
889+
OMPI_F08_IGNORE_TKR_PREDECL="no attribute required for"
890+
OMPI_F08_BINDINGS_EXTENSION="ts"
891+
OMPI_F08_BINDINGS_TS_SUFFIX="ts"],
892+
[OMPI_F08_IGNORE_TKR_TYPE=$OMPI_FORTRAN_IGNORE_TKR_TYPE
893+
OMPI_F08_IGNORE_TKR_PREDECL=${OMPI_FORTRAN_IGNORE_TKR_PREDECL:1}
894+
OMPI_F08_BINDINGS_EXTENSION="f"
895+
OMPI_F08_BINDINGS_TS_SUFFIX=""])
896+
AC_SUBST(OMPI_F08_BINDINGS_EXTENSION)
897+
AC_SUBST(OMPI_F08_BINDINGS_TS_SUFFIX)
898+
866899
# Somewhat redundant because ompi/Makefile.am won't traverse into
867900
# ompi/mpi/fortran/use-mpi-f08 if it's not to be built, but we
868901
# might as well have ompi/mpi/fortran/use-mpi-f08/Makefile.am be

docs/developers/bindings.rst

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
C and Fortran Bindings
2+
======================
3+
4+
The C and Fortran (mpi_f08) bindings are generated from Python code in
5+
``ompi/mpi/bindings``. Both the language bindings are generated from
6+
template files for each function. In the C case, each template file corresponds
7+
to a single generated C file, while in the Fortran case there are three major
8+
files generated for all functions.
9+
10+
The Python code depends on special prototype lines used with both the C and
11+
Fortran bindings. These "prototypes" are designed to be easy to parse and use
12+
specific type constants that can be mapped directly to the expanded
13+
language-specific code, error-handling, and conversion code.
14+
15+
C Bindings
16+
----------
17+
18+
This will walk through adding (or converting) a plain-C binding into a
19+
templated version controlled by the script.
20+
21+
As an example, for ``MPI_Send`` you might have a C file that looks something
22+
like this:
23+
24+
.. code-block:: c
25+
26+
#include "ompi_config.h"
27+
...other includes...
28+
29+
int MPI_Send(const void *buf, int count, MPI_Datatype datatype, int dest,
30+
int tag, MPI_Comm comm)
31+
{
32+
...internal checks...
33+
return internal_mpi_send(buf, count, datatype, dest, tag, comm);
34+
}
35+
36+
To convert this to a template, you will have to first ensure that only a single
37+
function is defined in the file, removing or abstracting out static functions,
38+
and separating multiple definitions, such as ``MPI_Send`` and ``MPI_Isend``,
39+
into different files. The template should also not include any macro-processing
40+
that attempts to change the name of the function or parameter types; this code
41+
should be generated by the script, or abstracted into header files that can
42+
work easily with multiple functions.
43+
44+
At this point, the template should look like the example above, with a "header"
45+
section, with simple includes or macros, maybe a static global, and the
46+
function defintion and nothing else.
47+
48+
The next step is to convert the signature line into the prototype format that
49+
the script expects. For ``MPI_Send``, this should look something like this:
50+
51+
.. code-block:: c
52+
53+
PROTOTYPE ERROR_CLASS send(BUFFER buf, COUNT count, DATATYPE type, RANK dest,
54+
TAG tag, COMM comm)
55+
56+
Notice how the function name is changed, the ``MPI_`` prefix removed and the
57+
rest converted to lowercase, and also how each parameter is simplified into a
58+
``TYPE name`` format, where the ``TYPE`` conforms to an allowed list in
59+
``ompi/mpi/bindings/ompi_bindings/c_type.py``. For newer functions and types,
60+
you may have to extend the ``c_type.py`` file with a new class showing how to
61+
handle the type.
62+
63+
The final step is to update ``Makefile.am``, adding the template name, in this
64+
case ``send.c.in``, to the ``prototype_sources`` variable, and the generated
65+
file name, ``generated_send.c``, to ``interface_profile_sources``. The
66+
generated file name must be of the form ``generated_${basename}.c``, where
67+
``${basename}`` is the name of the template file stripped of all extensions.
68+
69+
Fortran Bindings
70+
----------------
71+
72+
Adding new Fortran bindings follows a similar process to the C version above.
73+
All new interfaces are actually based on a single C-template file following the
74+
same format as the C interface templates. However, the C file generated will
75+
use Fortran-specific arguments, including ``CFI_*`` arguments, when TS 29113 is
76+
enabled, ``MPI_Fint *`` arguments in other cases, and others specific to how
77+
the Fortran MPI types are defined. Most of these files perform Fortran-specific
78+
error handling, Fortran-to-C type conversion, and other necessary steps before
79+
calling the actually C bindings with the proper arguments.
80+
81+
These templates are used not only to generate a C backing file for the Fortran
82+
code, but also the Fortran interface definitions and the Fortran subroutines
83+
corresponding to the generated C file. These are output in three separate files:
84+
85+
* ``ompi/mpi/fortran/use-mpi-f08/api_f08_generated.F90``
86+
* ``ompi/mpi/fortran/use-mpi-f08/base/api_f08_generated.c``
87+
* ``ompi/mpi/fortran/use-mpi-f08/mod/mpi-f08-interfaces-generated.h``
88+
89+
The Fortran file ``api_f08_generated.F90`` contains all the internal subroutine
90+
definitions, each of which makes a call into corresponding C functions. The
91+
internal subroutine names are mapped to the external interface, including
92+
multiple interfaces for the bigcount version of functions, in
93+
``mpi-f08-interfaces-generated.h``. The C file ``api_f08_generated.c``
94+
basically contains a concatenation of all fully expanded C templates.
95+
These files contain preprocessing directives to ensure they can support
96+
compilers with and without TS 29113 support, allowing use of
97+
``CFI_cdesc_t`` types when available (see `Fortran 2018`_ for more details).
98+
99+
.. _Fortran 2018: https://fortranwiki.org/fortran/show/Fortran+2018
100+
101+
If a new type needs to be added, then one will need to extend
102+
``fortran_type.py`` in ``ompi/mpi/bindings/ompi_bindings`` with an additional
103+
type class specifying how to handle the type in the above generated files,
104+
including any required key-value attributes for more complicated types. New
105+
types use a ``Type`` base class with functions that can be implemented by
106+
derived classes, each returning expanded Fortran or C code.
107+
108+
Other Considerations
109+
--------------------
110+
111+
Keep in mind that the generated files will not be deleted with a ``make clean``
112+
or ``make distclean``; instead use ``make maintainer-clean`` to delete those.

docs/developers/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ probably don't need to read this section.
2222
gnu-autotools
2323
sphinx
2424
rst-for-markdown-expats.rst
25+
bindings

docs/developers/prerequisites.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,15 @@ build them manually, see the :ref:`how to build and install GNU
4747
Autotools section <developers-installing-autotools-label>` for much
4848
more detail.
4949

50+
Python
51+
------
52+
53+
Python >= v3.6 is required for generating the Fortran bindings, which
54+
is necessary if you build Open MPI from a Git clone.
55+
56+
Python is also required for running Sphinx to generate the docs, too
57+
(:ref:`see below <developers-requirements-sphinx-label>`).
58+
5059
Perl
5160
----
5261

@@ -88,6 +97,8 @@ MacPorts on MacOS), see `the Flex Github repository
8897
<https://github.com/westes/flex>`_.
8998

9099

100+
.. _developers-requirements-sphinx-label:
101+
91102
Sphinx (and therefore Python)
92103
-----------------------------
93104

0 commit comments

Comments
 (0)