Generator Guide

Introduction to the generators

The main generator within WI4MPI is responsible of the MPI functions generation used to pass the appropriate arguments to the underlying runtime MPI function. It handle the generation of MPI C routines for the interface and preload version of WI4MPI.

These file generations are driven by the python command <wi4mpi_dir>/src/generator/generator.py. This contains the Generator class that will generate the C code files and headers. The different generation tasks have been organized in several python modules and submodules all present in the ‘src/generator’ folder. The python command has several options such as target versions of OpenMPI, MPICH and IntelMPI or the target MPI norm.

Some functions are not implemented yet due to their complexity, but in order to have a Frozen API, they have to be added to the generated files. Those functions trigger an MPI_Abort when they are used.

Quick generation

Requirements

  • Prepend wi4mpi_dir/src/generator in your PYTHONPATH

  • The generator uses clang-format -style=LLVM to format C files. So you must have clang-format in your PATH

  • The generator needs following python modules: docopt jsonschema logging jinja2

Execution

wi4mpi_dir/src/generator/generate.py will print in the standard output the following lines:

generator_logger - INFO - Starting to generate.
header_logger - INFO - MpcHeaderGenerator in progress.
header_logger - WARNING - The generation of 'src/interface/header/_MPC/wrapper_f.h' have to be done locally.
        A MPC program has to be executed in order to catch MPI_MODE_XXX values.
        Have a look to generator/FORTRAN/MPI_XXX_generator/MPC/gen_MPC_vars.sh
header_logger - INFO - IntelHeaderGenerator in progress.
header_logger - INFO - MpichHeaderGenerator in progress.
header_logger - INFO - OmpiHeaderGenerator in progress.
header_logger - INFO - IntelIntelHeaderGenerator in progress.
header_logger - INFO - IntelMpichHeaderGenerator in progress.
header_logger - INFO - MpichIntelHeaderGenerator in progress.
header_logger - INFO - MpichMpichHeaderGenerator in progress.
header_logger - INFO - IntelOmpiHeaderGenerator in progress.
header_logger - INFO - MpichOmpiHeaderGenerator in progress.
header_logger - INFO - OmpiIntelHeaderGenerator in progress.
header_logger - INFO - OmpiMpichHeaderGenerator in progress.
header_logger - INFO - OmpiOmpiHeaderGenerator in progress.
code_logger - INFO - Generation of preload C file.
code_logger - INFO - Generation of interface C file.
generator_logger - INFO - End

All log messages are written in generator.log.

Without any options, the generator will overwrite the header files in directories

  • <build_dir>/src/interface/header/_*

  • <build_dir>/src/preload/header/*_*

and generated code files in directories

  • <build_dir>/src/interface/gen/

  • <build_dir>/src/preload/gen/

Header generator

Dedicated settings

The following options are dedicated to the header generator:

--interface_header_dir=<interface_header_dir>                      Path to header interface generation folder.
--preload_header_dir=<preload_header_dir>                          Path to header preload generation folder.
--openmpi_version=<openmpi_version>                                Version of the target OpenMPI
--mpich_version=<mpich_version>                                    Version of the target MPICH
--intelmpi_version=<intelmpi_version>                              Version of the target IntelMPI

The options for defining the paths of the generation folders are detailed in Output directories.

Options for defining versions of MPI implementations are detailed in Version numbers

Output directories

The paths to the directories where the interface and preload headers are written are configurable by the following options:

  • --interface_header_dir set the Generator class attribute interface_header_dir. Default value: src/interface/header

  • --preload_header_dir set the Generator class attribute preload_header_dir. Default value: src/preload/header

The subfolders in which the headers are actually written follow the nomenclature <APP_side_name>_<RUN_side_name>.

Table 2 and Table 3 can be consulted for an overview of the distribution of headers in the subfolders of interface_header_dir and preload_header_dir.

Version numbers

The version numbers of the MPI implementations whose headers are used as the basis for producing the wi4mpi headers are configurable by the following options:

  • --openmpi_version set openmpi_version, the version of the target OpenMPI. Default value: 5.0.3

  • --mpich_version set mpich_version, the version of the target MPICH. Default value: 4.2.0

  • --intelmpi_version set intelmpi_version, the version of the target IntelMPI. Default value: 24.0.0

For each of the previous options, if defined, the value of the dictionary mpi_target_version (attribute of the Generator class) corresponding to the name of the implementation will be updated

The version number of each implementation will then be retrieved in the following way within the Generator class and its subclasses: self.mpi_target_version["<implementation_name>"]

Warning

A check for version support for each implementation is performed in the initialization of the Generator class. If the number is not in the mpi_availabe_target_version dictionary (attribute of the Generator class) then it will return an error and stop the generation.

Currently supported versions are:

  • OpenMPI: 1.8.8, 2.1.6, 4.1.6, 5.0.3

  • MPICH: 3.1.2, 3.4.3, 4.2.0

  • IntelMPI: 20.0.0, 24.0.0

Aliases

An alias system has been implemented in the generator.py file and allows only the major number of the MPI implementation version to be passed in argument. Concretely, this involves associating the major number with the highest supported version number. For this the alias_<implementation_name> dictionaries are used:

alias_openmpi = {
    "1": "1.8.8",
    "2": "2.1.6",
    "4": "4.1.6",
    "5": "5.0.3",
}
alias_mpich = {
    "3": "3.4.3",
    "4": "4.2.0",
}
alias_intelmpi = {
    "20": "20.0.0",
    "24": "24.0.0",
}

Workflow

As can be seen in the graph below, the --interface_header_dir and --preload_header_dir options pass the prefixes of the writing directories of the preload and interface headers to the generator when initializing an object of the Generator class. Their value is stored in the interface_header_dir and preload_header_dir class attributes when calling the set_directories method.

digraph G { rankdir=TB; // Orientation from top to bottom // rankdir=LB; // Orientation from Rleft to right // // Classes definition: // subgraph cluster_class_Generator { label=<<B>Generator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Output: parallelogram node [shape=parallelogram, style=filled, fillcolor=red]; preload_header_dir; interface_header_dir; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; Generator__init__ [label="__init__"]; Generator_set_directories [label="set_directories"]; // Links Generator__init__ -> Generator_set_directories; Generator_set_directories -> interface_header_dir; Generator_set_directories -> preload_header_dir; } // // Input: parallelogram // node [shape=parallelogram, style=filled, fillcolor=green]; option_preload_dir [label="--preload_header_dir", shape=parallelogram]; option_interface_dir [label="--interface_header_dir", shape=parallelogram]; // // Data Flow // option_preload_dir -> Generator__init__; option_interface_dir -> Generator__init__; }

Fig. 5 Set header directories prefix

Tip

Default values are src/interface/header and src/preload/header

Then, the creation of these folders is done during the initialization of each header generation class during the execution of the Generator.generate() method. We can see for example the case of the generation of Intel-Intel preload headers on the graph Create header directories prefix. The value of preload_header_dir previously defined during the initialization step of the Generator class is transmitted to the set_directories method of the main HeaderGenerator class which then calls the os.makedirs builtin to create the <preload_header_dir>/INTEL_INTEL subfolder.

digraph G { rankdir=TB; // Orientation from top to bottom // rankdir=LB; // Orientation from Rleft to right // // Classes definition: // subgraph cluster_class_Generator { label=<<B>Generator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Output: parallelogram node [shape=parallelogram, style=filled, fillcolor=grey]; preload_header_dir; interface_header_dir; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; Generator_generate [label="generate"]; // Generator_generate_code [label="generate_code"]; Generator_generate_header [label="generate_header"]; // Links Generator_generate -> Generator_generate_header; interface_header_dir -> Generator_generate_header; preload_header_dir -> Generator_generate_header; } subgraph cluster_class_IntelIntelHeaderGenerator { label=<<B>IntelIntelHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; IntelIntelHeaderGenerator__init__ [label="__init__"]; } subgraph cluster_class_IntelHeaderGenerator { label=<<B>IntelHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; IntelHeaderGenerator__init__ [label="__init__"]; } subgraph cluster_class_HeaderGenerator { label=<<B>HeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; HeaderGenerator__init__ [label="__init__"]; HeaderGenerator_set_directories [label="set_directories"]; // Output: parallelogram node [shape=parallelogram, style=filled, fillcolor=red]; HeaderGenerator_dir_input [label="dir_input"]; HeaderGenerator_dir_output [label="dir_output"]; // Links HeaderGenerator__init__ -> HeaderGenerator_set_directories; HeaderGenerator_set_directories -> HeaderGenerator_dir_input; HeaderGenerator_set_directories -> HeaderGenerator_dir_output; } // node [shape=ellipse, style=filled, fillcolor=orange]; makedirs [label="os.makedirs"] // node [shape=folder, style=filled, fillcolor=red]; INTEL_INTEL [label="<preload_header_dir>/INTEL_INTEL"] // // // Functionnal relationship // Generator_generate_header -> IntelIntelHeaderGenerator__init__ [label="dir_output=<preload_header_dir>+INTEL_INTEL \n dir_input=src/preload/header/scripts/intel_intel_headers"]; IntelIntelHeaderGenerator__init__ -> IntelHeaderGenerator__init__; IntelHeaderGenerator__init__ -> HeaderGenerator__init__; HeaderGenerator_set_directories -> makedirs [label="dir_output"]; // // Data Flow // makedirs -> INTEL_INTEL; }

Fig. 6 Create header directories prefix

Once the folders are created, it is the turn of the header files. The actions concerning them, illustrated on the graph, are also triggered by the generate method of each generation class. The basic headers are first copied from <dir_input> to <dir_output>. To do this, the app and run attributes are used to form the strings of the file names to be copied. This excerpt from the code of the copy_files method illustrates the Intel-Intel case:

input_file_name = f"{self.app}-{self.mpi_target_version[f'{self.app}']}_mpio.h"
self.copy_file(input_file_name, "app_mpio.h")
input_file_name = f"{self.app}-{self.mpi_target_version[f'{self.app}']}_mpi.h"
self.copy_file(input_file_name, "app_mpi.h")

input_file_name = f"{self.run}-{self.mpi_target_version[f'{self.run}']}_mpio.h"
self.copy_file(input_file_name, "run_mpio.h")
input_file_name = f"{self.run}-{self.mpi_target_version[f'{self.run}']}_mpi.h"
self.copy_file(input_file_name, "run_mpi.h")

The names and paths of the files to be copied and their destination are passed one by one to the copy_file method.

Tip

The names of the final files are defined in the HeaderGenerator class.

_run_mpi_header_file = "run_mpi.h"
_run_mpio_header_file = "run_mpio.h"
_app_mpi_header_file = "app_mpi.h"
_app_mpio_header_file = "app_mpio.h"
_wrapper_f_header_file = "wrapper_f.h"
_run_mpi_proto_header_file = "run_mpi_proto.h"
_app_mpi_proto_header_file = "app_mpi_proto.h"
digraph G { rankdir=TB; // Orientation from top to bottom // rankdir=LB; // Orientation from Rleft to right // // Classes definition: // subgraph cluster_class_Generator { label=<<B>Generator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; Generator_generate [label="generate"]; // Generator_generate_code [label="generate_code"]; Generator_generate_header [label="generate_header"]; // Links Generator_generate -> Generator_generate_header; } subgraph cluster_class_IntelIntelHeaderGenerator { label=<<B>IntelIntelHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; node [shape=parallelogram, style=filled, fillcolor=green]; IntelIntelHeaderGenerator_app [label="app=intelmpi"]; IntelIntelHeaderGenerator_run [label="run=intelmpi"]; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; IntelIntelHeaderGenerator_generate [label="generate"]; } subgraph cluster_class_IntelHeaderGenerator { label=<<B>IntelHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; IntelHeaderGenerator_generate [label="generate"]; } subgraph cluster_class_HeaderGenerator { label=<<B>HeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; HeaderGenerator_generate [label="generate"]; HeaderGenerator_copy_files [label="copy_files"]; HeaderGenerator_copy_file [label="copy_file"]; // Output: parallelogram node [shape=parallelogram, style=filled, fillcolor=grey]; dir_input; dir_output; // Links HeaderGenerator_generate -> HeaderGenerator_copy_files; HeaderGenerator_copy_files -> HeaderGenerator_copy_file [label="<input_file_name>\n<output_file_name>"]; dir_input -> HeaderGenerator_copy_files; dir_output -> HeaderGenerator_copy_files; } // node [shape=ellipse, style=filled, fillcolor=orange]; copy [label="shutil.copy2"] // node [shape=folder, style=filled, fillcolor=red]; INTEL_INTEL [label="<preload_header_dir>/INTEL_INTEL"] // // // Functionnal relationship // Generator_generate_header -> IntelIntelHeaderGenerator_generate [label="dir_output=<preload_header_dir>+INTEL_INTEL \n dir_input=src/preload/header/scripts/intel_intel_headers"]; IntelIntelHeaderGenerator_generate -> IntelHeaderGenerator_generate; IntelHeaderGenerator_generate -> HeaderGenerator_generate; HeaderGenerator_copy_file -> copy ; // // Data Flow // copy -> INTEL_INTEL [label="run_mpi.h app_mpi.h run_mpio.h"]; IntelIntelHeaderGenerator_app -> HeaderGenerator_copy_files; IntelIntelHeaderGenerator_run -> HeaderGenerator_copy_files; }

Fig. 7 Copy header files

Then the copied files are modified by the following methods:

_generate_run_mpih
_generate_run_mpioh
_generate_app_mpih
_generate_app_mpioh
_generate_run_mpi_protoh
_generate_app_mpi_protoh
_generate_wrapper_fh

All these methods are defined in the main class HeaderGenerator. They can then be overridden in subclasses dedicated to each combination <APP>-<RUN> of MPI implementation. Various methods are used to pool file modifications. Thus, the complete description of the workflow for generating each header can be complex.

Preload mode: IntelMPI application side – IntelMPI runtime side

run_mpi.h

The generation of the header run_mpi.h in the Intel-Intel case is illustrated in the graph below. An object of the class IntelIntelHeaderGenerator is initialized in the method generate_header of the class Generator. The method generate of IntelIntelHeaderGenerator is inherited from the class HeaderGenerator by the class IntelHeaderGenerator. We find there the call to the method dedicated to the generation of the file run_mpi.h: _generate_run_mpih. This will successively call intel_generate_run_mpih (from the IntelHeaderGenerator class) and intel_preload_exception_header_run_mpih. The first method applies the common modifications made by _replace_mpi_with_rmpi from the HeaderGenerator class and those of intel_exceptions_run_mpih. The modifications are then saved in run_mpi.h. Finally, intel_preload_exception_header_run_mpih applies the latest modifications. To do this, a file from src/resources/generator_datader containing substitution instructions is passed to the replacement_from_conf_file function and lines are deleted by the delete_lines function. These two functions belong to the textoperator module.

digraph G { rankdir=TB; // Orientation from top to bottom // rankdir=LB; // Orientation from Rleft to right // // Classes definition: // subgraph cluster_class_Generator { label=<<B>Generator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; Generator_generate [label="generate"]; // Generator_generate_code [label="generate_code"]; Generator_generate_header [label="generate_header"]; // Links Generator_generate -> Generator_generate_header; } subgraph cluster_class_IntelIntelHeaderGenerator { label=<<B>IntelIntelHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; node [shape=parallelogram, style=filled, fillcolor=green]; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; IntelIntelHeaderGenerator_generate [label="generate"]; IntelIntelHeaderGenerator__generate_run_mpih [label="_generate_run_mpih"]; IntelIntelHeaderGenerator_intel_preload_exception_header_run_mpih [label="intel_preload_exception_header_run_mpih"]; // IntelIntelHeaderGenerator__generate_run_mpioh [label="_generate_run_mpioh"]; // IntelIntelHeaderGenerator__generate_app_mpih [label="_generate_app_mpih"]; // IntelIntelHeaderGenerator__generate_app_mpioh [label="_generate_app_mpioh"]; // IntelIntelHeaderGenerator__generate_run_mpi_protoh [label="_generate_run_mpi_protoh"]; // IntelIntelHeaderGenerator__generate_app_mpi_protoh [label="_generate_app_mpi_protoh"]; // IntelIntelHeaderGenerator__generate_wrapper_fh [label="_generate_wrapper_fh"]; // Links IntelIntelHeaderGenerator__generate_run_mpih -> IntelIntelHeaderGenerator_intel_preload_exception_header_run_mpih; } subgraph cluster_class_IntelHeaderGenerator { label=<<B>IntelHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; IntelHeaderGenerator_generate [label="generate"]; IntelHeaderGenerator_intel_generate_run_mpih [label="intel_generate_run_mpih"]; IntelHeaderGenerator_intel_exceptions_run_mpih [label="intel_exceptions_run_mpih"]; // Links IntelHeaderGenerator_intel_generate_run_mpih -> IntelHeaderGenerator_intel_exceptions_run_mpih; } subgraph cluster_class_HeaderGenerator { label=<<B>HeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; HeaderGenerator_generate [label="generate"]; HeaderGenerator__replace_mpi_with_rmpi [label="_replace_mpi_with_rmpi"]; // Output: parallelogram // Links } // Module definition: rectangle subgraph cluster_module_textoperator { label=<<B>textoperator</B>>; labeljust="l"; color=red; style=rounded; bgcolor=lightsalmon; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; textoperator_replacement_from_conf_file [label="replacement_from_conf_file"]; textoperator_delete_lines [label="delete_lines"]; } node [shape=ellipse, style=filled, fillcolor=orange]; resub [label="re.sub"]; // node [shape=folder, style=filled, fillcolor=red]; INTEL_INTEL [label="<preload_header_dir>/INTEL_INTEL"] node [shape=folder, style=filled, fillcolor=green]; etc [label="etc/header"]; // // // Functionnal relationship // Generator_generate_header -> IntelIntelHeaderGenerator_generate; IntelIntelHeaderGenerator_generate -> IntelHeaderGenerator_generate; IntelHeaderGenerator_generate -> HeaderGenerator_generate; HeaderGenerator_generate -> IntelIntelHeaderGenerator__generate_run_mpih; IntelIntelHeaderGenerator__generate_run_mpih -> IntelHeaderGenerator_intel_generate_run_mpih; IntelHeaderGenerator_intel_generate_run_mpih -> HeaderGenerator__replace_mpi_with_rmpi; HeaderGenerator__replace_mpi_with_rmpi -> resub; IntelHeaderGenerator_intel_exceptions_run_mpih -> resub; IntelHeaderGenerator_intel_exceptions_run_mpih -> textoperator_delete_lines; // // Data Flow // IntelIntelHeaderGenerator__generate_run_mpih -> INTEL_INTEL; IntelHeaderGenerator_intel_generate_run_mpih -> INTEL_INTEL; etc -> IntelIntelHeaderGenerator_intel_preload_exception_header_run_mpih; IntelIntelHeaderGenerator_intel_preload_exception_header_run_mpih -> textoperator_delete_lines; IntelIntelHeaderGenerator_intel_preload_exception_header_run_mpih -> textoperator_replacement_from_conf_file; IntelIntelHeaderGenerator_intel_preload_exception_header_run_mpih -> resub; }

Fig. 8 Generating run_mpi.h for IntelMPI application side – IntelMPI runtime side

app_mpi.h
digraph G { rankdir=TB; // Orientation from top to bottom // rankdir=LB; // Orientation from Rleft to right // // Classes definition: // subgraph cluster_class_Generator { label=<<B>Generator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; Generator_generate [label="generate"]; // Generator_generate_code [label="generate_code"]; Generator_generate_header [label="generate_header"]; // Links Generator_generate -> Generator_generate_header; } subgraph cluster_class_IntelIntelHeaderGenerator { label=<<B>IntelIntelHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; node [shape=parallelogram, style=filled, fillcolor=green]; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; IntelIntelHeaderGenerator_generate [label="generate"]; IntelIntelHeaderGenerator__generate_app_mpih [label="_generate_app_mpih"]; IntelIntelHeaderGenerator__generate_run_mpih [label="_generate_run_mpih"]; IntelIntelHeaderGenerator__common_generate_app_mpih [label="_common_generate_app_mpih"]; // Links IntelIntelHeaderGenerator__generate_app_mpih -> IntelIntelHeaderGenerator__generate_run_mpih; IntelIntelHeaderGenerator__generate_app_mpih -> IntelIntelHeaderGenerator__common_generate_app_mpih; } subgraph cluster_class_IntelHeaderGenerator { label=<<B>IntelHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; IntelHeaderGenerator_generate [label="generate"]; } subgraph cluster_class_HeaderGenerator { label=<<B>HeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; HeaderGenerator_generate [label="generate"]; } // Module definition: rectangle subgraph cluster_module_textoperator { label=<<B>textoperator</B>>; labeljust="l"; color=red; style=rounded; bgcolor=lightsalmon; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; textoperator_replacement_from_conf_file [label="replacement_from_conf_file"]; } node [shape=ellipse, style=filled, fillcolor=orange]; resub [label="re.sub"]; // node [shape=folder, style=filled, fillcolor=red]; INTEL_INTEL [label="<preload_header_dir>/INTEL_INTEL"] node [shape=folder, style=filled, fillcolor=green]; etc [label="etc/header"]; // // // Functionnal relationship // Generator_generate_header -> IntelIntelHeaderGenerator_generate; IntelIntelHeaderGenerator_generate -> IntelHeaderGenerator_generate; IntelHeaderGenerator_generate -> HeaderGenerator_generate; HeaderGenerator_generate -> IntelIntelHeaderGenerator__generate_app_mpih; IntelIntelHeaderGenerator__common_generate_app_mpih -> textoperator_replacement_from_conf_file; IntelIntelHeaderGenerator__common_generate_app_mpih -> resub; // // Data Flow // etc -> IntelIntelHeaderGenerator__common_generate_app_mpih; IntelIntelHeaderGenerator__common_generate_app_mpih -> INTEL_INTEL; }

Fig. 9 Generating app_mpi.h for IntelMPI application side – IntelMPI runtime side

run_mpio.h
digraph G { rankdir=TB; // Orientation from top to bottom // rankdir=LB; // Orientation from Rleft to right // // Classes definition: // subgraph cluster_class_Generator { label=<<B>Generator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; Generator_generate [label="generate"]; Generator_generate_header [label="generate_header"]; // Links Generator_generate -> Generator_generate_header; } subgraph cluster_class_IntelIntelHeaderGenerator { label=<<B>IntelIntelHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; node [shape=parallelogram, style=filled, fillcolor=green]; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; IntelIntelHeaderGenerator_generate [label="generate"]; IntelIntelHeaderGenerator__generate_run_mpioh [label="_generate_run_mpioh"]; // Links } subgraph cluster_class_IntelHeaderGenerator { label=<<B>IntelHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; IntelHeaderGenerator_generate [label="generate"]; IntelHeaderGenerator__generate_run_mpioh [label="_generate_run_mpioh"]; IntelHeaderGenerator_intel_exceptions_run_mpioh [label="intel_exceptions_run_mpioh"] // Links } subgraph cluster_class_HeaderGenerator { label=<<B>HeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; HeaderGenerator_generate [label="generate"]; HeaderGenerator__generate_run_mpioh [label="_generate_run_mpioh"]; HeaderGenerator__replace_mpi_with_rmpi [label="_replace_mpi_with_rmpi"]; HeaderGenerator_intel_exceptions_run_mpioh [label="intel_exceptions_run_mpioh"] // Output: parallelogram // Links HeaderGenerator__generate_run_mpioh -> HeaderGenerator__replace_mpi_with_rmpi; HeaderGenerator__generate_run_mpioh -> HeaderGenerator_intel_exceptions_run_mpioh; } // Module definition: rectangle subgraph cluster_module_textoperator { label=<<B>textoperator</B>>; labeljust="l"; color=red; style=rounded; bgcolor=lightsalmon; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; textoperator_replacement_from_conf_file [label="replacement_from_conf_file"]; textoperator_delete_lines [label="delete_lines"]; } node [shape=ellipse, style=filled, fillcolor=orange]; resub [label="re.sub"]; // node [shape=folder, style=filled, fillcolor=red]; INTEL_INTEL [label="<preload_header_dir>/INTEL_INTEL"] // node [shape=folder, style=filled, fillcolor=green]; // etc [label="etc/header"]; // // // Functionnal relationship // Generator_generate_header -> IntelIntelHeaderGenerator_generate; IntelIntelHeaderGenerator_generate -> IntelHeaderGenerator_generate; IntelHeaderGenerator_generate -> HeaderGenerator_generate; // // HeaderGenerator_generate -> IntelIntelHeaderGenerator__generate_run_mpih; HeaderGenerator_generate -> IntelIntelHeaderGenerator__generate_run_mpioh; IntelIntelHeaderGenerator__generate_run_mpioh -> IntelHeaderGenerator__generate_run_mpioh; IntelHeaderGenerator__generate_run_mpioh -> HeaderGenerator__generate_run_mpioh; // IntelHeaderGenerator_intel_generate_run_mpih -> HeaderGenerator__replace_mpi_with_rmpi; HeaderGenerator__replace_mpi_with_rmpi -> resub; HeaderGenerator_intel_exceptions_run_mpioh -> IntelHeaderGenerator_intel_exceptions_run_mpioh; IntelHeaderGenerator_intel_exceptions_run_mpioh -> resub; IntelHeaderGenerator_intel_exceptions_run_mpioh -> textoperator_delete_lines; IntelHeaderGenerator_intel_exceptions_run_mpioh -> textoperator_replacement_from_conf_file; // // Data Flow // HeaderGenerator__generate_run_mpioh -> INTEL_INTEL [label="run_mpio.h"]; // IntelHeaderGenerator_intel_generate_run_mpih -> INTEL_INTEL; // etc -> IntelIntelHeaderGenerator_intel_preload_exception_header_run_mpih; // IntelIntelHeaderGenerator_intel_preload_exception_header_run_mpih -> textoperator_delete_lines; // IntelIntelHeaderGenerator_intel_preload_exception_header_run_mpih -> resub; }

Fig. 10 Generating run_mpio.h for IntelMPI application side – IntelMPI runtime side

app_mpio.h
digraph G { rankdir=TB; // Orientation from top to bottom // rankdir=LB; // Orientation from Rleft to right // // Classes definition: // subgraph cluster_class_Generator { label=<<B>Generator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; Generator_generate [label="generate"]; Generator_generate_header [label="generate_header"]; // Links Generator_generate -> Generator_generate_header; } subgraph cluster_class_IntelIntelHeaderGenerator { label=<<B>IntelIntelHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; node [shape=parallelogram, style=filled, fillcolor=green]; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; IntelIntelHeaderGenerator_generate [label="generate"]; IntelIntelHeaderGenerator__generate_app_mpioh [label="_generate_app_mpioh"]; IntelIntelHeaderGenerator__common_generate_app_mpioh [label="_common_generate_app_mpioh"]; node [shape=ellipse, style=filled, fillcolor=purple]; IntelIntelHeaderGenerator__generate_run_mpioh [label="_generate_run_mpioh"]; // Links IntelIntelHeaderGenerator__generate_app_mpioh -> IntelIntelHeaderGenerator__generate_run_mpioh; IntelIntelHeaderGenerator__generate_app_mpioh -> IntelIntelHeaderGenerator__common_generate_app_mpioh; } subgraph cluster_class_IntelHeaderGenerator { label=<<B>IntelHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; IntelHeaderGenerator_generate [label="generate"]; } subgraph cluster_class_HeaderGenerator { label=<<B>HeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; HeaderGenerator_generate [label="generate"]; // Output: parallelogram // Links } // Module definition: rectangle subgraph cluster_module_textoperator { label=<<B>textoperator</B>>; labeljust="l"; color=red; style=rounded; bgcolor=lightsalmon; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; textoperator_replacement_from_conf_file [label="replacement_from_conf_file"]; textoperator_delete_lines [label="delete_lines"]; } // node [shape=ellipse, style=filled, fillcolor=orange]; // resub [label="re.sub"]; // node [shape=folder, style=filled, fillcolor=red]; INTEL_INTEL [label="<preload_header_dir>/INTEL_INTEL"] node [shape=folder, style=filled, fillcolor=green]; etc [label="etc/header"]; // // // Functionnal relationship // Generator_generate_header -> IntelIntelHeaderGenerator_generate; IntelIntelHeaderGenerator_generate -> IntelHeaderGenerator_generate; IntelHeaderGenerator_generate -> HeaderGenerator_generate; HeaderGenerator_generate -> IntelIntelHeaderGenerator__generate_app_mpioh; IntelIntelHeaderGenerator__common_generate_app_mpioh -> textoperator_replacement_from_conf_file; IntelIntelHeaderGenerator__common_generate_app_mpioh -> textoperator_delete_lines; // HeaderGenerator_generate -> IntelIntelHeaderGenerator__generate_app_mpih; // // Data Flow // etc -> IntelIntelHeaderGenerator__common_generate_app_mpioh; // IntelIntelHeaderGenerator -> INTEL_INTEL; IntelIntelHeaderGenerator__generate_app_mpioh -> INTEL_INTEL; }

Fig. 11 Generating app_mpio.h for IntelMPI application side – IntelMPI runtime side (short workflow)

digraph G { rankdir=TB; // Orientation from top to bottom // rankdir=LB; // Orientation from Rleft to right // // Classes definition: // subgraph cluster_class_Generator { label=<<B>Generator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; Generator_generate [label="generate"]; Generator_generate_header [label="generate_header"]; // Links Generator_generate -> Generator_generate_header; } subgraph cluster_class_IntelIntelHeaderGenerator { label=<<B>IntelIntelHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; node [shape=parallelogram, style=filled, fillcolor=green]; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; IntelIntelHeaderGenerator_generate [label="generate"]; IntelIntelHeaderGenerator__generate_app_mpioh [label="_generate_app_mpioh"]; IntelIntelHeaderGenerator__generate_run_mpioh [label="_generate_run_mpioh"]; IntelIntelHeaderGenerator__common_generate_app_mpioh [label="_common_generate_app_mpioh"]; IntelHeaderGenerator_intel_exceptions_run_mpioh [label="intel_exceptions_run_mpioh"] // Links IntelIntelHeaderGenerator__generate_app_mpioh -> IntelIntelHeaderGenerator__generate_run_mpioh; IntelIntelHeaderGenerator__generate_app_mpioh -> IntelIntelHeaderGenerator__common_generate_app_mpioh; } subgraph cluster_class_IntelHeaderGenerator { label=<<B>IntelHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; IntelHeaderGenerator_generate [label="generate"]; IntelHeaderGenerator__generate_run_mpioh [label="_generate_run_mpioh"]; } subgraph cluster_class_HeaderGenerator { label=<<B>HeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; HeaderGenerator_generate [label="generate"]; HeaderGenerator__generate_run_mpioh [label="_generate_run_mpioh"]; HeaderGenerator__replace_mpi_with_rmpi [label="_replace_mpi_with_rmpi"]; HeaderGenerator_intel_exceptions_run_mpioh [label="intel_exceptions_run_mpioh"] // Output: parallelogram // Links HeaderGenerator__generate_run_mpioh -> HeaderGenerator__replace_mpi_with_rmpi; HeaderGenerator__generate_run_mpioh -> HeaderGenerator_intel_exceptions_run_mpioh; } // Module definition: rectangle subgraph cluster_module_textoperator { label=<<B>textoperator</B>>; labeljust="l"; color=red; style=rounded; bgcolor=lightsalmon; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; textoperator_replacement_from_conf_file [label="replacement_from_conf_file"]; textoperator_delete_lines [label="delete_lines"]; } node [shape=ellipse, style=filled, fillcolor=orange]; resub [label="re.sub"]; // node [shape=folder, style=filled, fillcolor=red]; INTEL_INTEL [label="<preload_header_dir>/INTEL_INTEL"] node [shape=folder, style=filled, fillcolor=green]; etc [label="etc/header"]; // // // Functionnal relationship // Generator_generate_header -> IntelIntelHeaderGenerator_generate; IntelIntelHeaderGenerator_generate -> IntelHeaderGenerator_generate; IntelHeaderGenerator_generate -> HeaderGenerator_generate; HeaderGenerator_generate -> IntelIntelHeaderGenerator__generate_app_mpioh; IntelIntelHeaderGenerator__common_generate_app_mpioh -> textoperator_replacement_from_conf_file; IntelIntelHeaderGenerator__common_generate_app_mpioh -> textoperator_delete_lines; IntelIntelHeaderGenerator__generate_run_mpioh -> IntelHeaderGenerator__generate_run_mpioh; IntelHeaderGenerator__generate_run_mpioh -> HeaderGenerator__generate_run_mpioh; HeaderGenerator__replace_mpi_with_rmpi -> resub; HeaderGenerator_intel_exceptions_run_mpioh -> IntelHeaderGenerator_intel_exceptions_run_mpioh; IntelHeaderGenerator_intel_exceptions_run_mpioh -> resub; IntelHeaderGenerator_intel_exceptions_run_mpioh -> textoperator_delete_lines; IntelHeaderGenerator_intel_exceptions_run_mpioh -> textoperator_replacement_from_conf_file; // HeaderGenerator_generate -> IntelIntelHeaderGenerator__generate_app_mpih; // // Data Flow // etc -> IntelIntelHeaderGenerator__common_generate_app_mpioh; etc -> IntelHeaderGenerator_intel_exceptions_run_mpioh; // IntelIntelHeaderGenerator -> INTEL_INTEL; IntelIntelHeaderGenerator__generate_app_mpioh -> INTEL_INTEL; }

Fig. 12 Generating app_mpio.h for IntelMPI application side – IntelMPI runtime side

IntelMPI interface mode

run_mpi.h
digraph G { rankdir=TB; // Orientation from top to bottom // rankdir=LB; // Orientation from Rleft to right // // Classes definition: // subgraph cluster_class_Generator { label=<<B>Generator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; Generator_generate [label="generate"]; Generator_generate_header [label="generate_header"]; // Links Generator_generate -> Generator_generate_header; } subgraph cluster_class_IntelHeaderGenerator { label=<<B>IntelHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; IntelHeaderGenerator_generate [label="generate"]; IntelHeaderGenerator__generate_run_mpih [label="_generate_run_mpih"]; IntelHeaderGenerator_intel_generate_run_mpih [label="intel_generate_run_mpih"]; IntelHeaderGenerator_intel_exceptions_run_mpih [label="intel_exceptions_run_mpih"]; // Links IntelHeaderGenerator__generate_run_mpih -> IntelHeaderGenerator_intel_generate_run_mpih; IntelHeaderGenerator__generate_run_mpih -> IntelHeaderGenerator_intel_exceptions_run_mpih; } subgraph cluster_class_HeaderGenerator { label=<<B>HeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; HeaderGenerator_generate [label="generate"]; HeaderGenerator__replace_mpi_with_rmpi [label="_replace_mpi_with_rmpi"]; } // Module definition: rectangle subgraph cluster_module_textoperator { label=<<B>textoperator</B>>; labeljust="l"; color=red; style=rounded; bgcolor=lightsalmon; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; // textoperator_replacement_from_conf_file [label="replacement_from_conf_file"]; textoperator_delete_lines [label="delete_lines"]; } node [shape=ellipse, style=filled, fillcolor=orange]; resub [label="re.sub"]; // node [shape=folder, style=filled, fillcolor=red]; _INTEL [label="<interface_header_dir>/_INTEL"] // node [shape=folder, style=filled, fillcolor=green]; // etc [label="etc/header"]; // // // Functionnal relationship // Generator_generate_header -> IntelHeaderGenerator_generate; IntelHeaderGenerator_generate -> HeaderGenerator_generate; HeaderGenerator_generate -> IntelHeaderGenerator__generate_run_mpih; IntelHeaderGenerator_intel_generate_run_mpih-> HeaderGenerator__replace_mpi_with_rmpi; IntelHeaderGenerator_intel_exceptions_run_mpih -> textoperator_delete_lines; IntelHeaderGenerator_intel_exceptions_run_mpih -> resub; HeaderGenerator__replace_mpi_with_rmpi -> resub; // // Data Flow // IntelHeaderGenerator_intel_generate_run_mpih -> _INTEL; // etc -> IntelIntelHeaderGenerator; // IntelIntelHeaderGenerator -> INTEL_INTEL; }

Fig. 13 Generating run_mpi.h for IntelMPI

app_mpi.h
digraph G { rankdir=TB; // Orientation from top to bottom // rankdir=LB; // Orientation from Rleft to right // // Classes definition: // subgraph cluster_class_Generator { label=<<B>Generator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; Generator_generate [label="generate"]; Generator_generate_header [label="generate_header"]; // Links Generator_generate -> Generator_generate_header; } subgraph cluster_class_IntelHeaderGenerator { label=<<B>IntelHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; IntelHeaderGenerator_generate [label="generate"]; // IntelHeaderGenerator_intel_generate_run_mpih [label="intel_generate_run_mpih"]; // IntelHeaderGenerator_intel_exceptions_run_mpih [label="intel_exceptions_run_mpih"]; // Links // IntelHeaderGenerator__generate_run_mpih -> IntelHeaderGenerator_intel_generate_run_mpih; // IntelHeaderGenerator__generate_run_mpih -> IntelHeaderGenerator_intel_exceptions_run_mpih; } subgraph cluster_class_HeaderGenerator { label=<<B>HeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; HeaderGenerator_generate [label="generate"]; HeaderGenerator__generate_app_mpih [label="_generate_app_mpih"]; HeaderGenerator__common_generate_app_mpih [label="_common_generate_app_mpih"]; // HeaderGenerator__replace_mpi_with_rmpi [label="_replace_mpi_with_rmpi"]; // Links HeaderGenerator__generate_app_mpih -> HeaderGenerator__common_generate_app_mpih; } // Module definition: rectangle subgraph cluster_module_textoperator { label=<<B>textoperator</B>>; labeljust="l"; color=red; style=rounded; bgcolor=lightsalmon; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; textoperator_replacement_from_conf_file [label="replacement_from_conf_file"]; textoperator_delete_lines [label="delete_lines"]; textoperator_replace_bloc_from_conf_file [label="replace_bloc_from_conf_file"]; textoperator_function_to_delete [label="function_to_delete"]; textoperato_delete_bloc_from_conf_file [label="delete_bloc_from_conf_file"]; textoperator_delete_line_from_pattern [label="delete_line_from_pattern"]; } node [shape=ellipse, style=filled, fillcolor=orange]; resub [label="re.sub"]; // node [shape=folder, style=filled, fillcolor=red]; _INTEL [label="<interface_header_dir>/_INTEL"] node [shape=folder, style=filled, fillcolor=green]; etc [label="etc/header"]; // // // Functionnal relationship // Generator_generate_header -> IntelHeaderGenerator_generate; IntelHeaderGenerator_generate -> HeaderGenerator_generate; HeaderGenerator_generate -> HeaderGenerator__generate_app_mpih; HeaderGenerator__common_generate_app_mpih -> textoperator_delete_lines; HeaderGenerator__common_generate_app_mpih -> textoperator_replacement_from_conf_file; HeaderGenerator__common_generate_app_mpih -> textoperator_replace_bloc_from_conf_file; HeaderGenerator__common_generate_app_mpih -> textoperator_function_to_delete; HeaderGenerator__common_generate_app_mpih -> textoperato_delete_bloc_from_conf_file; HeaderGenerator__common_generate_app_mpih -> textoperator_delete_line_from_pattern; HeaderGenerator__common_generate_app_mpih -> resub; // // Data Flow // HeaderGenerator__generate_app_mpih -> _INTEL; etc -> HeaderGenerator__common_generate_app_mpih; // etc -> IntelIntelHeaderGenerator; // IntelIntelHeaderGenerator -> INTEL_INTEL; }

Fig. 14 Generating app_mpi.h for IntelMPI

run_mpio.h
digraph G { rankdir=TB; // Orientation from top to bottom // rankdir=LB; // Orientation from Rleft to right // // Classes definition: // subgraph cluster_class_Generator { label=<<B>Generator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; Generator_generate [label="generate"]; Generator_generate_header [label="generate_header"]; // Links Generator_generate -> Generator_generate_header; } subgraph cluster_class_IntelHeaderGenerator { label=<<B>IntelHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; IntelHeaderGenerator_generate [label="generate"]; IntelHeaderGenerator__generate_run_mpioh [label="_generate_run_mpioh"]; IntelHeaderGenerator_intel_exceptions_run_mpioh [label="intel_exceptions_run_mpioh"]; // IntelHeaderGenerator_intel_generate_run_mpih [label="intel_generate_run_mpih"]; // IntelHeaderGenerator_intel_exceptions_run_mpih [label="intel_exceptions_run_mpih"]; // Links // IntelHeaderGenerator__generate_run_mpih -> IntelHeaderGenerator_intel_generate_run_mpih; // IntelHeaderGenerator__generate_run_mpih -> IntelHeaderGenerator_intel_exceptions_run_mpih; } subgraph cluster_class_HeaderGenerator { label=<<B>HeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; HeaderGenerator_generate [label="generate"]; HeaderGenerator__generate_run_mpioh [label="_generate_run_mpioh"]; HeaderGenerator__replace_mpi_with_rmpi [label="_replace_mpi_with_rmpi"]; HeaderGenerator_intel_exceptions_run_mpioh [label="intel_exceptions_run_mpioh"]; // Links HeaderGenerator__generate_run_mpioh -> HeaderGenerator__replace_mpi_with_rmpi; HeaderGenerator__generate_run_mpioh -> HeaderGenerator_intel_exceptions_run_mpioh; } // Module definition: rectangle subgraph cluster_module_textoperator { label=<<B>textoperator</B>>; labeljust="l"; color=red; style=rounded; bgcolor=lightsalmon; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; textoperator_replacement_from_conf_file [label="replacement_from_conf_file"]; textoperator_delete_lines [label="delete_lines"]; } node [shape=ellipse, style=filled, fillcolor=orange]; resub [label="re.sub"]; // node [shape=folder, style=filled, fillcolor=red]; _INTEL [label="<interface_header_dir>/_INTEL"] node [shape=folder, style=filled, fillcolor=green]; etc [label="etc/header"]; // // // Functionnal relationship // Generator_generate_header -> IntelHeaderGenerator_generate; IntelHeaderGenerator_generate -> HeaderGenerator_generate; HeaderGenerator_generate -> IntelHeaderGenerator__generate_run_mpioh; IntelHeaderGenerator__generate_run_mpioh -> HeaderGenerator__generate_run_mpioh; HeaderGenerator_intel_exceptions_run_mpioh -> IntelHeaderGenerator_intel_exceptions_run_mpioh; IntelHeaderGenerator_intel_exceptions_run_mpioh -> textoperator_replacement_from_conf_file; IntelHeaderGenerator_intel_exceptions_run_mpioh -> textoperator_delete_lines; IntelHeaderGenerator_intel_exceptions_run_mpioh -> resub; // IntelHeaderGenerator_intel_generate_run_mpih-> HeaderGenerator__replace_mpi_with_rmpi; // IntelHeaderGenerator_intel_exceptions_run_mpih -> textoperator_delete_lines; // IntelHeaderGenerator_intel_exceptions_run_mpih -> resub; HeaderGenerator__replace_mpi_with_rmpi -> resub; // // Data Flow // HeaderGenerator__generate_run_mpioh -> _INTEL; etc -> IntelHeaderGenerator_intel_exceptions_run_mpioh; // etc -> IntelIntelHeaderGenerator; // IntelIntelHeaderGenerator -> INTEL_INTEL; }

Fig. 15 Generating run_mpio.h for IntelMPI

OpenMPI interface mode

run_mpi.h
digraph G { rankdir=TB; // Orientation from top to bottom // rankdir=LB; // Orientation from Rleft to right // // Classes definition: // subgraph cluster_class_Generator { label=<<B>Generator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; Generator_generate [label="generate"]; Generator_generate_header [label="generate_header"]; // Links Generator_generate -> Generator_generate_header; } subgraph cluster_class_OmpiHeaderGenerator { label=<<B>OmpiHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; OmpiHeaderGenerator_generate [label="generate"]; OmpiHeaderGenerator__generate_run_mpih [label="_generate_run_mpih"]; OmpiHeaderGenerator_ompi_replace_mpi_with_rmpi [label="ompi_replace_mpi_with_rmpi"]; // Links OmpiHeaderGenerator__generate_run_mpih -> OmpiHeaderGenerator_ompi_replace_mpi_with_rmpi; } subgraph cluster_class_HeaderGenerator { label=<<B>HeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; HeaderGenerator_generate [label="generate"]; HeaderGenerator__generate_run_mpioh [label="_generate_run_mpih"]; // HeaderGenerator__replace_mpi_with_rmpi [label="_replace_mpi_with_rmpi"]; // HeaderGenerator_intel_exceptions_run_mpioh [label="intel_exceptions_run_mpioh"]; // Links // HeaderGenerator__generate_run_mpioh -> HeaderGenerator__replace_mpi_with_rmpi; // HeaderGenerator__generate_run_mpioh -> HeaderGenerator_intel_exceptions_run_mpioh; } // Module definition: rectangle subgraph cluster_module_textoperator { label=<<B>textoperator</B>>; labeljust="l"; color=red; style=rounded; bgcolor=lightsalmon; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; textoperator_replacement_from_conf_file [label="replacement_from_conf_file"]; textoperator_delete_lines [label="delete_lines"]; textoperator_function_to_delete [label="function_to_delete"]; } node [shape=ellipse, style=filled, fillcolor=orange]; resub [label="re.sub"]; // node [shape=folder, style=filled, fillcolor=red]; _OMPI [label="<interface_header_dir>/_OMPI"] node [shape=folder, style=filled, fillcolor=green]; etc [label="etc/header"]; // // // Functionnal relationship // Generator_generate_header -> OmpiHeaderGenerator_generate; OmpiHeaderGenerator_generate -> HeaderGenerator_generate; HeaderGenerator_generate -> OmpiHeaderGenerator__generate_run_mpih; OmpiHeaderGenerator_ompi_replace_mpi_with_rmpi -> textoperator_replacement_from_conf_file; OmpiHeaderGenerator_ompi_replace_mpi_with_rmpi -> textoperator_delete_lines; OmpiHeaderGenerator_ompi_replace_mpi_with_rmpi -> textoperator_function_to_delete; OmpiHeaderGenerator_ompi_replace_mpi_with_rmpi -> resub; // // Data Flow // OmpiHeaderGenerator__generate_run_mpih -> _OMPI; etc -> OmpiHeaderGenerator_ompi_replace_mpi_with_rmpi; }

Fig. 16 Generating run_mpi.h for OpenMPI

app_mpi.h
digraph G { rankdir=TB; // Orientation from top to bottom // rankdir=LB; // Orientation from Rleft to right // // Classes definition: // subgraph cluster_class_Generator { label=<<B>Generator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; Generator_generate [label="generate"]; Generator_generate_header [label="generate_header"]; // Links Generator_generate -> Generator_generate_header; } subgraph cluster_class_OmpiHeaderGenerator { label=<<B>OmpiHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; OmpiHeaderGenerator_generate [label="generate"]; } subgraph cluster_class_HeaderGenerator { label=<<B>HeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; HeaderGenerator_generate [label="generate"]; HeaderGenerator__generate_app_mpih [label="_generate_app_mpih"]; HeaderGenerator__common_generate_app_mpih [label="_common_generate_app_mpih"]; // HeaderGenerator__replace_mpi_with_rmpi [label="_replace_mpi_with_rmpi"]; // Links HeaderGenerator__generate_app_mpih -> HeaderGenerator__common_generate_app_mpih; } // Module definition: rectangle subgraph cluster_module_textoperator { label=<<B>textoperator</B>>; labeljust="l"; color=red; style=rounded; bgcolor=lightsalmon; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; textoperator_replacement_from_conf_file [label="replacement_from_conf_file"]; textoperator_delete_lines [label="delete_lines"]; textoperator_replace_bloc_from_conf_file [label="replace_bloc_from_conf_file"]; textoperator_function_to_delete [label="function_to_delete"]; textoperato_delete_bloc_from_conf_file [label="delete_bloc_from_conf_file"]; textoperator_delete_line_from_pattern [label="delete_line_from_pattern"]; } node [shape=ellipse, style=filled, fillcolor=orange]; resub [label="re.sub"]; // node [shape=folder, style=filled, fillcolor=red]; _OMPI [label="<interface_header_dir>/_OMPI"] node [shape=folder, style=filled, fillcolor=green]; etc [label="etc/header"]; // // // Functionnal relationship // Generator_generate_header -> OmpiHeaderGenerator_generate; OmpiHeaderGenerator_generate -> HeaderGenerator_generate; HeaderGenerator_generate -> HeaderGenerator__generate_app_mpih; HeaderGenerator__common_generate_app_mpih -> textoperator_delete_lines; HeaderGenerator__common_generate_app_mpih -> textoperator_replacement_from_conf_file; HeaderGenerator__common_generate_app_mpih -> textoperator_replace_bloc_from_conf_file; HeaderGenerator__common_generate_app_mpih -> textoperator_function_to_delete; HeaderGenerator__common_generate_app_mpih -> textoperato_delete_bloc_from_conf_file; HeaderGenerator__common_generate_app_mpih -> textoperator_delete_line_from_pattern; HeaderGenerator__common_generate_app_mpih -> resub; // // Data Flow // HeaderGenerator__generate_app_mpih -> _OMPI; etc -> HeaderGenerator__common_generate_app_mpih; // etc -> OmpiOmpiHeaderGenerator; // OmpiOmpiHeaderGenerator -> INTEL_INTEL; }

Fig. 17 Generating app_mpi.h for OpenMPI

MPICH interface mode

run_mpi.h
digraph G { rankdir=TB; // Orientation from top to bottom // rankdir=LB; // Orientation from Rleft to right // // Classes definition: // subgraph cluster_class_Generator { label=<<B>Generator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; Generator_generate [label="generate"]; Generator_generate_header [label="generate_header"]; // Links Generator_generate -> Generator_generate_header; } subgraph cluster_class_MpichHeaderGenerator { label=<<B>MpichHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; MpichHeaderGenerator_mpich_copyright [label="mpich_copyright"]; MpichHeaderGenerator_generate [label="generate"]; MpichHeaderGenerator__generate_run_mpih [label="_generate_run_mpih"]; MpichHeaderGenerator_mpich_generate_run_mpih [label="mpich_generate_run_mpih"]; // Links MpichHeaderGenerator__generate_run_mpih -> MpichHeaderGenerator_mpich_generate_run_mpih; MpichHeaderGenerator__generate_run_mpih -> MpichHeaderGenerator_mpich_copyright; } subgraph cluster_class_IntelHeaderGenerator { label=<<B>IntelHeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; IntelHeaderGenerator_intel_generate_run_mpih [label="intel_generate_run_mpih"]; IntelHeaderGenerator__generate_run_mpih [label="_generate_run_mpih"]; IntelHeaderGenerator_intel_exceptions_run_mpih [label="intel_exceptions_run_mpih"]; // Links IntelHeaderGenerator__generate_run_mpih -> IntelHeaderGenerator_intel_generate_run_mpih; } subgraph cluster_class_HeaderGenerator { label=<<B>HeaderGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; HeaderGenerator_generate [label="generate"]; // HeaderGenerator__generate_run_mpih [label="_generate_run_mpih"]; HeaderGenerator__replace_mpi_with_rmpi [label="_replace_mpi_with_rmpi"]; // Links } // Module definition: rectangle subgraph cluster_module_textoperator { label=<<B>textoperator</B>>; labeljust="l"; color=red; style=rounded; bgcolor=lightsalmon; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; // textoperator_replacement_from_conf_file [label="replacement_from_conf_file"]; textoperator_delete_lines [label="delete_lines"]; // textoperator_replace_bloc_from_conf_file [label="replace_bloc_from_conf_file"]; // textoperator_function_to_delete [label="function_to_delete"]; // textoperato_delete_bloc_from_conf_file [label="delete_bloc_from_conf_file"]; // textoperator_delete_line_from_pattern [label="delete_line_from_pattern"]; } node [shape=ellipse, style=filled, fillcolor=orange]; resub [label="re.sub"]; // node [shape=folder, style=filled, fillcolor=red]; _MPICH [label="<interface_header_dir>/_MPICH"] // node [shape=folder, style=filled, fillcolor=green]; // etc [label="etc/header"]; // // // Functionnal relationship // Generator_generate_header -> MpichHeaderGenerator_generate; MpichHeaderGenerator_generate -> HeaderGenerator_generate; MpichHeaderGenerator_mpich_generate_run_mpih -> IntelHeaderGenerator__generate_run_mpih [dir=both]; HeaderGenerator_generate -> MpichHeaderGenerator__generate_run_mpih; IntelHeaderGenerator_intel_generate_run_mpih -> HeaderGenerator__replace_mpi_with_rmpi IntelHeaderGenerator_intel_generate_run_mpih -> IntelHeaderGenerator_intel_exceptions_run_mpih MpichHeaderGenerator_mpich_copyright -> resub; HeaderGenerator__replace_mpi_with_rmpi -> resub; IntelHeaderGenerator_intel_exceptions_run_mpih -> resub; IntelHeaderGenerator_intel_exceptions_run_mpih -> textoperator_delete_lines; // HeaderGenerator__common_generate_app_mpih -> textoperator_delete_lines; // HeaderGenerator__common_generate_app_mpih -> textoperator_replacement_from_conf_file; // HeaderGenerator__common_generate_app_mpih -> textoperator_replace_bloc_from_conf_file; // HeaderGenerator__common_generate_app_mpih -> textoperator_function_to_delete; // HeaderGenerator__common_generate_app_mpih -> textoperato_delete_bloc_from_conf_file; // HeaderGenerator__common_generate_app_mpih -> textoperator_delete_line_from_pattern; // HeaderGenerator__common_generate_app_mpih -> resub; // // Data Flow // MpichHeaderGenerator_mpich_generate_run_mpih -> _MPICH; // etc -> HeaderGenerator__common_generate_app_mpih; // etc -> OmpiOmpiHeaderGenerator; // OmpiOmpiHeaderGenerator -> INTEL_INTEL; }

Fig. 18 Generating run_mpi.h for MPICH

Code generator

Dedicated settings

The following options are dedicated to the code generator:

--c_preload_gen_dir=<c_preload_gen_dir>                            Path to C preload generation folder.
--c_interface_gen_dir=<c_interface_gen_dir>                        Path to C interface generation folder.
--mpi_norm=<mpi_norm>                                              Version of MPI norm to use

The options for defining the paths of the generation folders are detailed in Output directories.

Options for defining version of MPI norm are detailed in MPI norm

Output directories

The paths to the directories where the interface and preload generated C code are written are configurable by the following options:

  • --c_interface_header_dir set the Generator class attribute c_interface_header_dir. Default value: src/interface/gen

  • --c_preload_header_dir set the Generator class attribute c_preload_header_dir. Default value: src/preload/gen

MPI norm

The version number of the MPI standard in which the user wants to generate the C code (see C files) can be set by the --mpi_norm option. This option set the Generator class attribute mpi_norm which transmits the version through the generator. By default its value is 3.1

The list of supported versions is contained in mpi_available_norm:

mpi_availabe_norm = [ "1.0", "1.1", "1.2", "2.0", "2.1", "2.2", "3.0", "3.1", "4.0"]

This value is used to select the functions implemented in the chosen standard.

To do this, mpi_norm traverses the generator following the path of Fig. 19. Its value is transmitted to the header and code generator at the initialisation of a Generator object. It is compared to the MPImin and MPImax values of each object of the JSON file <wi4mpi_dir>/src/resources/generator_data/code/common/jsons/functions.json (see functions.json – C) This comparison is performed when the JSON is loaded in load_json_file. The result is a dictionary data["function"] containing all the functions of the standard.

digraph mpi_norm_workflow { rankdir=TB; // Orientation from top to bottom // Classes definition: subgraph cluster_class_Generator { label=<<B>Generator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Test node [shape=parallelogram, style=filled, fillcolor=grey]; Generator_mpi_norm [label="mpi_norm"]; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; Generator__init__ [label="__init__"]; Generator_generate [label="generate"]; Generator_generate_code [label="generate_code"]; Generator__init__ -> Generator_mpi_norm [label="If mpi_norm in\n mpi_available_norm"]; Generator_mpi_norm -> Generator_generate; Generator_generate -> Generator_generate_code; } subgraph cluster_class_CodeGenerator { label=<<B>CodeGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; CodeGenerator_set_directories [label="set_directories"]; CodeGenerator__init__ [label="__init__"]; // Output: parallelogram node [shape=parallelogram, style=filled, fillcolor=red]; CodeGenerator_data_functions [label="data[\"functions\"]"]; subgraph cluster_class_CPreloadGenerator { label=<<B>CPreloadGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; CPreloadGenerator__init__ [label="__init__"]; } subgraph cluster_class_CInterfaceGenerator { label=<<B>CInterfaceGenerator</B>>; labeljust="l"; color=blue; style=rounded; bgcolor=lightblue; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; CInterfaceGenerator__init__ [label="__init__"]; } } // Module definition: rectangle subgraph cluster_module_textoperator { label=<<B>textoperator</B>>; labeljust="l"; color=red; style=rounded; bgcolor=lightsalmon; // Method definition: ellipse node [shape=ellipse, style=filled, fillcolor=orange]; textoperator_load_json_file [label="load_json_file"]; textoperator_is_block_valid_for_mpi [label="_is_block_valid_for_mpi"]; } // Input: parallelogram node [shape=parallelogram, style=filled, fillcolor=green]; functions_json [label="functions.json"]; mpi_norm [shape=parallelogram]; // Functionnal relationship Generator_generate_code -> CPreloadGenerator__init__; Generator_generate_code -> CInterfaceGenerator__init__; CPreloadGenerator__init__ -> CodeGenerator__init__; CInterfaceGenerator__init__ -> CodeGenerator__init__; CodeGenerator__init__ -> CodeGenerator_set_directories; CodeGenerator_set_directories -> textoperator_load_json_file; textoperator_load_json_file -> textoperator_is_block_valid_for_mpi [label=mpi_norm]; textoperator_is_block_valid_for_mpi -> textoperator_load_json_file [label="<bool>"]; // Data Flow mpi_norm -> Generator__init__; Generator_generate_code -> functions_json [label="<dir_input>", style=dashed]; functions_json -> CodeGenerator_set_directories [style=dashed]; textoperator_load_json_file -> CodeGenerator_set_directories [label="data"]; CodeGenerator_set_directories -> CodeGenerator_data_functions; }

Fig. 19 Worflow of mpi_norm

Note

If a json schema is given as an argument to the load_json_file function then the python jsonschema module will be used to validate the json file given for reading.

Currently the schema used to validate the previous functions.json is <wi4mpi_dir>/src/resources/generator_data/code/common/jsons/schemas/schema_functions.json In particular, it requires the presence of the keyword MPImin.

Generation template

File template handling C MPI routines for interface and preload version:

  1. Non generated function integration

  2. Normal MPI_… declaration

  3. Function pointer to the underlying runtime MPI routine declaration

  4. ASM code chooser

  5. A_MPI_… declaration + function construction

    1. Header

    2. Temporary variable assignment, and translation

    3. Call to the MPI runtime function

    4. Footer

    5. return

  6. R_MPI_… declaration + function construction

    1. Header

    2. Call to the MPI runtime function

    3. Footer

    4. return

  7. Attribute constructor init generation

Generating function connection:

  1. print_symbol_c

  2. print_symbol_c

  3. object_gen.generate_func_asmK_tls / generate_func_asmK_tls_updated_for_interface

  4. generate_func_c

    1. header_func

    2. print_temporary_decl_c + affect_temp_conv_c

    3. print_symbol_c + affect_val_conv_c

    4. footer_func

  5. generate_func_r

    1. header_func

    2. print_symbol_c

    3. footer_func

The Fortran MPI routines template is quite similar. The step 6 and 4 are specific to this version.

Function and mappers dictionaries

functions.json – C

Example:

MPI_Init(int *, char***);
{
"args": [
{ **1st argument**

    "var": "argc", **name**

    "arg_dep": "", **dependency**

    "In": 1, **The argument need to be converted before any call to the underlying MPI runtime call**

    "name": "int_ptr_mapper", **name of the mapper corresponding to that argument (mappers are responsible for the translation)**

    "Out": 0 **The argument do not need to be converted after the MPI runtime call**

},
{ **2nd argument**

    "var": "argv",

    "arg_dep": "",

    "In": 1,

    "name": "char_ppp_converter",

    "Out": 0

}

],

  "name": "MPI_Init",

  "ret":

  {

        "var": "ret",

        "arg_dep": "",

        "In": 0,

        "name": "error_converter",

        "Out": 1

  },

  "MPImin": 1.0,

  "MPImax": 4.0

}

Some additional key words to deal with some special cases:

  • if : Tell to the generating process that the argument needs to be translated only if the condition within the if statements is true.

  • if_null : Same as ‘if’ keyword but dedicated to NULL constants.

  • if_dep : If provided, then the generator automatically understand that the argument tested in the “if” condition is an array, and so a loop is generated from 0 to “if_dep” (‘if_dep’ works hand in hand with ‘if’).

  • if_null_dep : Same as ‘if_dep’ but works with ‘if_null’

  • if_err: Handle special case MPI_Errhandler_set.

  • del : The argument needs to be deleted from the mechanism managing the database (hashtable)

  • del2 : Same as ‘del’.

  • arg_dep: Same as ‘if_dep’ but works on its own.

See Table 1 to overview the association keywords.

Table 1 Association keywords

Wait & Test

Waitany & Waitany

Waitsome & Testsome

Waitall & Testall

if

R_MPI_SUCCESS

if_null

R_MPI_REQUEST_NULL

if_dep

NONE

NONE

(*)outcount

count

if_null_dep

NONE

NONE

array_of_indices

NONE

del

request_ptr_delete

del2

NONE

mappers.json – C

This file contains all different metadata about mappers that needs to be called to performed any conversion. Each entry is corresponding to the mappers name which is referenced in the function.json “name” keywords within any arguments function. Those entries provide metadata relevant for the generator as represented bellow:

"int_ptr_mapper": {     **name**

    "local_alloc": 0, **Does the variable needs to be allocated locally. 0=no; 1=yes**

    "a2r": "int_ptr_conv_a2r", **If 'in=1' from functions.json is set, then this function needs to be called**

    "type": "int (*)", **type of the argument**

    "r2a": "int_ptr_conv_r2a", **If 'out=1' from functions.json is set, then this function needs to be called**

    "no_map": "TRUE" **The argument does not need to be converted if 'TRUE'**

}

All relevent keywords that a mappers can contain are:

  • no_map : indicate if the argument needs to be converted

  • assign : indicate that the arguments simply needs a cast

  • local_alloc : indicate that the variable needs to be allocated locally

  • wrap : Special case where the argument ‘wrap’ is a function pointer. (example MPI_Op_create)

  • wrapped : ‘wrapped’ contain the function name which is called to translate the arguments of the function referenced by ‘wrap’.

Example of “wrap” and “wrapped”: “wrapper_user_function”

When a call to A_MPI_Op_create(A_MPI_User_function * user_fn,int commute,A_MPI_Op * op);, the user_fn et op arguments needs to be converted

int A_MPI_Op_create(A_MPI_User_function * user_fn,int commute,A_MPI_Op * op)
{

    in_w=1;

    ptr_user_func=(A_MPI_User_function * )user_fn;

    R_MPI_Op  op_ltmp;

    R_MPI_Op * op_tmp=&op_ltmp;

    int ret_tmp= LOCAL_MPI_Op_create( (R_MPI_User_function * ) wrapper_user_function, commute, op_tmp);

    op_conv_r2a(op,op_tmp); **conversion de op**

    in_w=0;

    return error_code_conv_r2a(ret_tmp);

}

user_fn is a function pointer where (MPI_Datatype * ) is referenced:

typedef void (MPI_User_function) (void * , void * , int * , MPI_Datatype * );

Conversion de user_fn :

void wrapper_user_function(void * invec, void * inoutvec, int * len,R_MPI_Datatype * type)
{
    A_MPI_Datatype datatype_tmp;
    datatype_conv_r2a( &datatype_tmp,type);
    (ptr_user_func)(invec, inoutvec, len, & datatype_tmp);
}

The following keywords are set for user_fn in MPI_Op_create:

  • “wrap” : “user_fn”

  • “wrapped” : “wrapper_user_function”

functions.json – Fortran special case

Some special cases are handle thanks to the “assoc” field which allow to make some bounds between the hash table and both of the following parameters.

Exemple:

"assoc":[
    {
        "func":"Keyval_translation_del",
        "key":"keyval_tmp"
    }
]

mappers.json – Fortran special cases

The fields ‘nomap’ and ‘argdep’ got the same goal as ‘no_map’ and ‘arg_dep’ of C mappers.

Frozen API

In order to get the frozen API proceed as follow:

Just copy the contents of A the file into the B file:

A

B

interface_api_fige.c

<—>

interface/gen/test_wrapper_generation.c

interface_api_fige_fortran.c

<—>

interface/gen/wrapper.c

interface_api_fige_fortran_interface.c

<—>

interface/gen/interface_fort.c

preload_api_fige.c

<—>

preload/gen/test_wrapper_generation.c

preload_api_fige_fortran.c

<—>

preload/gen/wrapper.c

Input files

The generator will open several files during the proccess:

  • C header

  • JSON

  • jinja

  • raw text

Headers generator inputs

Base headers

The headers of each supported implementation are in <wi4mpi_dir>/src/resources/MPI_headers/ folder. Here is an overview of the tree structure:

<implementation_name>/
└── <version>
    └── mpi.h

with <implementation_name> equal to openmpi, mpich or intelmpi.

These files are used as a base from which Wi4MPI’s own headers will be generated.

How to add a new base header

Below is the procedure to follow to add a base header for the implementation <implementation_name> in the version <version>.

  1. [global]: Create the folder src/resources/MPI_headers/<implementation_name>/<version>

  2. [global]: Copy the headers inside the previous folder. The existing names are:

    • mpi.h

    • mpio.h (IntelMPI, MPICH)

    • mpi_proto.h (MPICH since 4.2.2)

  3. [src/generator/generator.py]: Add the <version> into the available versions dictionary: mpi_availabe_target_version

  4. [src/generator/generator.py]: Update the default version of the implementation by editing the dictionary mpi_target_version.

  5. [src/generator/generator.py]: Complete the helpers in the module description and in the docopt strings (below the __main__ check)

  6. [global]: If the implementation is new, create a file in the src/resources/MPI_headers/wrapperf/ directory similar to those existing

Now the new header is ready to be processed by the generator.

Files for regular expression

The re module is used to perform line-by-line or block-by-block replacements. The re.sub command is used directly in the code for small replacements.

For larger replacements, lists of commands are written in files placed in src/resources/generator_data/headers. Here is the exhaustive list of these files:

  • header._common_generate_app_mpih.replace

  • intelintelheader.__aux_generate_run_mpioh.replace

  • intelintelheader._common_generate_app_mpih.replace

  • intelintelheader._common_generate_app_mpioh.replace

  • intelintelheader._preload_exception_header_run_mpih.replace

  • intelompiheader.ompi_replace_mpi_with_rmpi.replace

  • mpcheader._mpc_exceptions_run_mpih.replace

  • ompiheader._replace_mpi_with_rmpi.ompiompi.replace

  • ompiheader._replace_mpi_with_rmpi.replace

  • ompiintelheader._app_to_run.replace

  • ompiintelheader._run_to_app.bloc_p0.replace

  • ompiintelheader._run_to_app.bloc_r0.replace

  • ompiintelheader._run_to_app.replace

They are the inputs to the textoperator.replacement_from_conf_file command.

Note

The separator used in replacement is @.

It is also possible to perform block replacements. For this, blocks of text to be searched and replaced are written in separate files. The following files are the inputs to the textoperator.replace_bloc_from_conf_file command:

  • header._common_generate_app_mpih.bloc_00.pattern

  • header._common_generate_app_mpih.bloc_00.replace

  • header._common_generate_app_mpih.bloc_01.pattern

  • header._common_generate_app_mpih.bloc_01.replace

  • header._common_generate_app_mpih.bloc_02.pattern

  • header._common_generate_app_mpih.bloc_02.replace

  • header._common_generate_app_mpih.bloc_06.pattern

  • header._common_generate_app_mpih.bloc_06.replace

  • header._common_generate_app_mpih.bloc_08a.pattern

  • header._common_generate_app_mpih.bloc_08.pattern

  • header._common_generate_app_mpih.bloc_08.replace

  • header._common_generate_app_mpih.bloc_09.pattern

  • header._common_generate_app_mpih.bloc_09.replace

Finally, the textoperator.delete_bloc_from_conf_file command, which is a special case of the previous command, allows you to search for and delete blocks of lines. The following files are used for this purpose:

  • header._common_generate_app_mpih.bloc_03.delete

  • header._common_generate_app_mpih.bloc_04.delete

  • header._common_generate_app_mpih.bloc_05.delete

  • header._common_generate_app_mpih.bloc_06.delete

  • header._common_generate_app_mpih.bloc_07.delete

  • header._common_generate_app_mpih.bloc_10.delete

Output files

The generator writes several files:

  • headers files

  • C files

  • log file

Header files

The concerned header files are

  • app_mpi.h: application side MPI header

  • run_mpi.h: runtime side MPI header

  • wrapper_f.h: interface version of the Fortran header

and, if applicable,

  • run_mpio.h

  • mpcmp.h: dedicated to MPC

  • sctk_types.h: dedicated to MPC

  • app_mpio.h

  • app_mpi_proto.h: additional file for MPICH from version 4.2.2

  • run_mpio.h

  • run_mpi_proto.h: additional file for MPICH from version 4.2.2

see Table 2 and Table 3 for an overview.

Table 2 Files in <wi4mpi_dir>/src/interface/header/<Folder>

Folder

app_mpi.h

run_mpi.h

wrapper_f.h

run_mpio.h

mpcmp.h

sctk_types.h

_INTEL

_MPC

_MPICH

(*)

_OMPI

Note

  • (*) additional file run_mpi_proto.h for MPICH from version 4.2.2

Table 3 Files in <wi4mpi_dir>/src/preload/header/<Folder>.

Folder

app_mpi.h

run_mpi.h

wrapper_f.h

app_mpio.h

run_mpio.h

INTEL_INTEL

INTEL_MPICH

(*)

INTEL_OMPI

MPICH_INTEL

(**)

MPICH_MPICH

(**)

(*)

MPICH_OMPI

(**)

OMPI_INTEL

OMPI_MPICH

(*)

OMPI_OMPI

Note

  • (*) additional file run_mpi_proto.h for MPICH from version 4.2.2

  • (**) additional file app_mpi_proto.h for MPICH from version 4.2.2

C files

The concerned code files are

  • <wi4mpi_dir>/src/preload/gen/mpi_translation_c.c

  • <wi4mpi_dir>/src/interface/gen/mpi_translation_c.c

  • <wi4mpi_dir>/src/interface/gen/interface_c.c

Log file

Warning, debug, info, error messages are written in file generator.log. They are managed by the python module logging and configured by <wi4mpi_dir>/src/generator/logging.conf.