├── docs
├── .nojekyll
├── html
│ ├── _static
│ │ ├── scripts
│ │ │ ├── furo-extensions.js
│ │ │ └── furo.js.LICENSE.txt
│ │ ├── file.png
│ │ ├── minus.png
│ │ ├── plus.png
│ │ ├── graphviz.css
│ │ ├── check-solid.svg
│ │ ├── documentation_options.js
│ │ ├── copy-button.svg
│ │ ├── custom.css
│ │ ├── debug.css
│ │ ├── copybutton.css
│ │ ├── copybutton_funcs.js
│ │ └── design-tabs.js
│ ├── objects.inv
│ ├── _images
│ │ ├── graphviz-57432295888f3b1be18dc2ff4389e53d44c4c869.png
│ │ ├── graphviz-610b9e33bc07bb04b4607643a1f9f6ac5fc1da80.png
│ │ ├── graphviz-684df2bb1f5f269b07d535b765e98e0faed34052.png
│ │ ├── graphviz-7106b06e7ffc5ab56026f5ac8ff442871e53c310.png
│ │ ├── graphviz-75a1f18eb87795bf7a08712374e54c8d1b2bd278.png
│ │ ├── graphviz-ac4fbb3880ee103a7ca5c201fb2dee5b4a532839.png
│ │ ├── graphviz-b254f1bb6c2aa092534cd14c8d6efccda1b3235f.png
│ │ ├── graphviz-b4b2d9f87128e4daea95a129e33a37e63efa7c98.png
│ │ ├── graphviz-d91f2fdebe3b7e20ff1761bf5a36baed7437423b.png
│ │ ├── graphviz-ead1119f5dbe0a448886914d18fd0cadedecdab1.png
│ │ ├── graphviz-f85f742f79de3c705c79ddaf4b344515c9beb90a.png
│ │ ├── graphviz-f85f742f79de3c705c79ddaf4b344515c9beb90a.png.map
│ │ ├── graphviz-57432295888f3b1be18dc2ff4389e53d44c4c869.png.map
│ │ ├── graphviz-d91f2fdebe3b7e20ff1761bf5a36baed7437423b.png.map
│ │ ├── graphviz-610b9e33bc07bb04b4607643a1f9f6ac5fc1da80.png.map
│ │ ├── graphviz-75a1f18eb87795bf7a08712374e54c8d1b2bd278.png.map
│ │ ├── graphviz-ac4fbb3880ee103a7ca5c201fb2dee5b4a532839.png.map
│ │ ├── graphviz-b4b2d9f87128e4daea95a129e33a37e63efa7c98.png.map
│ │ ├── graphviz-684df2bb1f5f269b07d535b765e98e0faed34052.png.map
│ │ ├── graphviz-7106b06e7ffc5ab56026f5ac8ff442871e53c310.png.map
│ │ ├── graphviz-b254f1bb6c2aa092534cd14c8d6efccda1b3235f.png.map
│ │ └── graphviz-ead1119f5dbe0a448886914d18fd0cadedecdab1.png.map
│ ├── _sources
│ │ ├── examples
│ │ │ ├── gather.rst.txt
│ │ │ ├── layouts.rst.txt
│ │ │ ├── file.rst.txt
│ │ │ ├── stl_container.rst.txt
│ │ │ ├── subarray.rst.txt
│ │ │ ├── standard_types.rst.txt
│ │ │ ├── distributed_grid.rst.txt
│ │ │ ├── gatherv.rst.txt
│ │ │ ├── probe.rst.txt
│ │ │ ├── communicator.rst.txt
│ │ │ ├── collective.rst.txt
│ │ │ ├── blocking.rst.txt
│ │ │ ├── matrix_gather.rst.txt
│ │ │ ├── hello_world.rst.txt
│ │ │ ├── blocking_vector.rst.txt
│ │ │ ├── distributed_grid_scatter_gather.rst.txt
│ │ │ ├── nonblocking_mult.rst.txt
│ │ │ ├── nonblocking.rst.txt
│ │ │ ├── arrays.rst.txt
│ │ │ ├── parallel_sort.rst.txt
│ │ │ ├── heat_equation_Jacobi_method.rst.txt
│ │ │ ├── reduce.rst.txt
│ │ │ ├── struct.rst.txt
│ │ │ ├── heat_equation_successive_over-relaxation.rst.txt
│ │ │ ├── vibrating_string.rst.txt
│ │ │ ├── custom_initialization.rst.txt
│ │ │ ├── iterators.rst.txt
│ │ │ ├── process_creation.rst.txt
│ │ │ └── index.rst.txt
│ │ ├── constants.rst.txt
│ │ ├── tags.rst.txt
│ │ ├── group.rst.txt
│ │ ├── info.rst.txt
│ │ ├── error.rst.txt
│ │ ├── grid.rst.txt
│ │ ├── environmental_management.rst.txt
│ │ ├── file.rst.txt
│ │ ├── auxiliary.rst.txt
│ │ ├── cmake_integration.rst.txt
│ │ ├── communicator.rst.txt
│ │ ├── design.rst.txt
│ │ ├── interoperability.rst.txt
│ │ └── layouts.rst.txt
│ └── _sphinx_design_static
│ │ └── design-tabs.js
└── mpl_parallel_2018.pdf
├── .gitignore
├── cmake
└── mplConfig.cmake
├── doc
├── sphinx
│ ├── examples
│ │ ├── layouts.rst
│ │ ├── gather.rst
│ │ ├── file.rst
│ │ ├── stl_container.rst
│ │ ├── subarray.rst
│ │ ├── standard_types.rst
│ │ ├── distributed_grid.rst
│ │ ├── gatherv.rst
│ │ ├── probe.rst
│ │ ├── communicator.rst
│ │ ├── collective.rst
│ │ ├── blocking.rst
│ │ ├── matrix_gather.rst
│ │ ├── hello_world.rst
│ │ ├── blocking_vector.rst
│ │ ├── nonblocking_mult.rst
│ │ ├── distributed_grid_scatter_gather.rst
│ │ ├── nonblocking.rst
│ │ ├── arrays.rst
│ │ ├── parallel_sort.rst
│ │ ├── heat_equation_Jacobi_method.rst
│ │ ├── reduce.rst
│ │ ├── struct.rst
│ │ ├── heat_equation_successive_over-relaxation.rst
│ │ ├── vibrating_string.rst
│ │ ├── custom_initialization.rst
│ │ ├── iterators.rst
│ │ ├── process_creation.rst
│ │ └── index.rst
│ ├── constants.rst
│ ├── file_error_handling.cc
│ ├── tags.rst
│ ├── _static
│ │ └── custom.css
│ ├── group.rst
│ ├── error.rst
│ ├── info.rst
│ ├── grid.rst
│ ├── environmental_management.rst
│ ├── file.rst
│ ├── auxiliary.rst
│ ├── cmake_integration.rst
│ ├── communicator.rst
│ ├── design.rst
│ ├── interoperability.rst
│ ├── layouts.rst
│ └── reduction_operations.rst
├── doxygen
│ └── data_types.md
└── CMakeLists.txt
├── mpl
├── message.hpp
├── displacements.hpp
├── ranks.hpp
├── mpl.hpp
├── vector.hpp
├── command_line.hpp
├── status.hpp
├── tag.hpp
└── error.hpp
├── test
├── test_displacements.cc
├── test_communicator_barrier.cc
├── test_info.cc
├── test_communicator_allgather.cc
├── test_dist_graph_communicator.cc
├── test_initialization.cc
├── test_helper.hpp
├── test_group.cc
├── test_graph_communicator.cc
├── test_communicator_bcast.cc
├── test_inter_communicator.cc
├── test_communicator_reduce_scatter.cc
├── test_communicator_scatter.cc
├── test_communicator_gather.cc
└── CMakeLists.txt
├── .clang-format
├── examples
├── process_creation.cc
├── nonblocking_mult.cc
├── process_creation_client.cc
├── process_creation_multiple.cc
├── hello_world.cc
├── file.cc
├── arrays.cc
├── gatherv.cc
├── communicator.cc
├── custom_initialization.cc
├── subarray.cc
├── intercommunicator.cc
├── blocking.cc
├── gather.cc
├── iterators.cc
├── probe.cc
├── reduce_min_loc.cc
├── reduce_lcm.cc
├── blocking_vector.cc
├── parallel_sort_mpl.cc
├── CMakeLists.txt
├── struct.cc
├── distributed_grid.cc
└── distributed_grid_scatter_gather.cc
├── .github
└── workflows
│ ├── build-with-mpich.yml
│ ├── build-with-openmpi.yml
│ └── build-with-IntelMPI.yml
├── .clang-tidy
├── COPYING
└── CMakeLists.txt
/docs/.nojekyll:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *build*/
2 |
--------------------------------------------------------------------------------
/docs/html/_static/scripts/furo-extensions.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/html/objects.inv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rabauke/mpl/HEAD/docs/html/objects.inv
--------------------------------------------------------------------------------
/docs/html/_static/file.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rabauke/mpl/HEAD/docs/html/_static/file.png
--------------------------------------------------------------------------------
/docs/html/_static/minus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rabauke/mpl/HEAD/docs/html/_static/minus.png
--------------------------------------------------------------------------------
/docs/html/_static/plus.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rabauke/mpl/HEAD/docs/html/_static/plus.png
--------------------------------------------------------------------------------
/docs/mpl_parallel_2018.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rabauke/mpl/HEAD/docs/mpl_parallel_2018.pdf
--------------------------------------------------------------------------------
/cmake/mplConfig.cmake:
--------------------------------------------------------------------------------
1 | include(CMakeFindDependencyMacro)
2 |
3 | find_dependency(Threads)
4 | find_dependency(MPI)
5 |
6 |
7 | include(${CMAKE_CURRENT_LIST_DIR}/mplTargets.cmake)
8 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/layouts.rst:
--------------------------------------------------------------------------------
1 | Layouts
2 | =======
3 |
4 | Construction and usage of various data layouts.
5 |
6 | .. literalinclude:: ../../../examples/layouts.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-57432295888f3b1be18dc2ff4389e53d44c4c869.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rabauke/mpl/HEAD/docs/html/_images/graphviz-57432295888f3b1be18dc2ff4389e53d44c4c869.png
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-610b9e33bc07bb04b4607643a1f9f6ac5fc1da80.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rabauke/mpl/HEAD/docs/html/_images/graphviz-610b9e33bc07bb04b4607643a1f9f6ac5fc1da80.png
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-684df2bb1f5f269b07d535b765e98e0faed34052.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rabauke/mpl/HEAD/docs/html/_images/graphviz-684df2bb1f5f269b07d535b765e98e0faed34052.png
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-7106b06e7ffc5ab56026f5ac8ff442871e53c310.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rabauke/mpl/HEAD/docs/html/_images/graphviz-7106b06e7ffc5ab56026f5ac8ff442871e53c310.png
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-75a1f18eb87795bf7a08712374e54c8d1b2bd278.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rabauke/mpl/HEAD/docs/html/_images/graphviz-75a1f18eb87795bf7a08712374e54c8d1b2bd278.png
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-ac4fbb3880ee103a7ca5c201fb2dee5b4a532839.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rabauke/mpl/HEAD/docs/html/_images/graphviz-ac4fbb3880ee103a7ca5c201fb2dee5b4a532839.png
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-b254f1bb6c2aa092534cd14c8d6efccda1b3235f.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rabauke/mpl/HEAD/docs/html/_images/graphviz-b254f1bb6c2aa092534cd14c8d6efccda1b3235f.png
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-b4b2d9f87128e4daea95a129e33a37e63efa7c98.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rabauke/mpl/HEAD/docs/html/_images/graphviz-b4b2d9f87128e4daea95a129e33a37e63efa7c98.png
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-d91f2fdebe3b7e20ff1761bf5a36baed7437423b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rabauke/mpl/HEAD/docs/html/_images/graphviz-d91f2fdebe3b7e20ff1761bf5a36baed7437423b.png
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-ead1119f5dbe0a448886914d18fd0cadedecdab1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rabauke/mpl/HEAD/docs/html/_images/graphviz-ead1119f5dbe0a448886914d18fd0cadedecdab1.png
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-f85f742f79de3c705c79ddaf4b344515c9beb90a.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/rabauke/mpl/HEAD/docs/html/_images/graphviz-f85f742f79de3c705c79ddaf4b344515c9beb90a.png
--------------------------------------------------------------------------------
/doc/sphinx/examples/gather.rst:
--------------------------------------------------------------------------------
1 | Gather operations
2 | =================
3 |
4 | Gathers data to a single process.
5 |
6 | .. literalinclude:: ../../../examples/gather.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/file.rst:
--------------------------------------------------------------------------------
1 | File i/o
2 | ========
3 |
4 | Simple program performing basic file-based i/o operations.
5 |
6 | .. literalinclude:: ../../../examples/file.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-f85f742f79de3c705c79ddaf4b344515c9beb90a.png.map:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/stl_container.rst:
--------------------------------------------------------------------------------
1 | STL containers
2 | ==============
3 |
4 | Sends and receives STL containers.
5 |
6 | .. literalinclude:: ../../../examples/stl_container.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/subarray.rst:
--------------------------------------------------------------------------------
1 | Subarray layouts
2 | ================
3 |
4 | Construction and usage of subarray layouts.
5 |
6 | .. literalinclude:: ../../../examples/subarray.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/gather.rst.txt:
--------------------------------------------------------------------------------
1 | Gather operations
2 | =================
3 |
4 | Gathers data to a single process.
5 |
6 | .. literalinclude:: ../../../examples/gather.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/layouts.rst.txt:
--------------------------------------------------------------------------------
1 | Layouts
2 | =======
3 |
4 | Construction and usage of various data layouts.
5 |
6 | .. literalinclude:: ../../../examples/layouts.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/file.rst.txt:
--------------------------------------------------------------------------------
1 | File i/o
2 | ========
3 |
4 | Simple program performing basic file-based i/o operations.
5 |
6 | .. literalinclude:: ../../../examples/file.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/stl_container.rst.txt:
--------------------------------------------------------------------------------
1 | STL containers
2 | ==============
3 |
4 | Sends and receives STL containers.
5 |
6 | .. literalinclude:: ../../../examples/stl_container.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/standard_types.rst:
--------------------------------------------------------------------------------
1 | Standard types
2 | ==============
3 |
4 | Sends and receives data of various standard types.
5 |
6 | .. literalinclude:: ../../../examples/standard_types.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-57432295888f3b1be18dc2ff4389e53d44c4c869.png.map:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-d91f2fdebe3b7e20ff1761bf5a36baed7437423b.png.map:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/subarray.rst.txt:
--------------------------------------------------------------------------------
1 | Subarray layouts
2 | ================
3 |
4 | Construction and usage of subarray layouts.
5 |
6 | .. literalinclude:: ../../../examples/subarray.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/distributed_grid.rst:
--------------------------------------------------------------------------------
1 | Distributed grid
2 | ================
3 |
4 | Data type ``mpl::distributed_grid`` in action.
5 |
6 | .. literalinclude:: ../../../examples/distributed_grid.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/gatherv.rst:
--------------------------------------------------------------------------------
1 | Variable gather operations
2 | ==========================
3 |
4 | Gathers data if varying size to a single process.
5 |
6 | .. literalinclude:: ../../../examples/gather.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/probe.rst:
--------------------------------------------------------------------------------
1 | Probing messages
2 | ================
3 |
4 | Demonstrates how to probe data and to receive a message of unknown size.
5 |
6 | .. literalinclude:: ../../../examples/probe.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/communicator.rst:
--------------------------------------------------------------------------------
1 | Communicator management
2 | =======================
3 |
4 | Demonstrates some basic communicator management.
5 |
6 | .. literalinclude:: ../../../examples/communicator.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/standard_types.rst.txt:
--------------------------------------------------------------------------------
1 | Standard types
2 | ==============
3 |
4 | Sends and receives data of various standard types.
5 |
6 | .. literalinclude:: ../../../examples/standard_types.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_static/graphviz.css:
--------------------------------------------------------------------------------
1 | /*
2 | * Sphinx stylesheet -- graphviz extension.
3 | */
4 |
5 | img.graphviz {
6 | border: 0;
7 | max-width: 100%;
8 | }
9 |
10 | object.graphviz {
11 | max-width: 100%;
12 | }
13 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/collective.rst:
--------------------------------------------------------------------------------
1 | Collective communication
2 | ========================
3 |
4 | Demonstrates various modes of collective communication.
5 |
6 | .. literalinclude:: ../../../examples/collective.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/distributed_grid.rst.txt:
--------------------------------------------------------------------------------
1 | Distributed grid
2 | ================
3 |
4 | Data type ``mpl::distributed_grid`` in action.
5 |
6 | .. literalinclude:: ../../../examples/distributed_grid.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/gatherv.rst.txt:
--------------------------------------------------------------------------------
1 | Variable gather operations
2 | ==========================
3 |
4 | Gathers data if varying size to a single process.
5 |
6 | .. literalinclude:: ../../../examples/gather.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/probe.rst.txt:
--------------------------------------------------------------------------------
1 | Probing messages
2 | ================
3 |
4 | Demonstrates how to probe data and to receive a message of unknown size.
5 |
6 | .. literalinclude:: ../../../examples/probe.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/communicator.rst.txt:
--------------------------------------------------------------------------------
1 | Communicator management
2 | =======================
3 |
4 | Demonstrates some basic communicator management.
5 |
6 | .. literalinclude:: ../../../examples/communicator.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/collective.rst.txt:
--------------------------------------------------------------------------------
1 | Collective communication
2 | ========================
3 |
4 | Demonstrates various modes of collective communication.
5 |
6 | .. literalinclude:: ../../../examples/collective.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/blocking.rst:
--------------------------------------------------------------------------------
1 | Blocking send and receive
2 | =========================
3 |
4 | Demonstrates various blocking send and receive modes of standard data types.
5 |
6 | .. literalinclude:: ../../../examples/blocking.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_static/scripts/furo.js.LICENSE.txt:
--------------------------------------------------------------------------------
1 | /*!
2 | * gumshoejs v5.1.2 (patched by @pradyunsg)
3 | * A simple, framework-agnostic scrollspy script.
4 | * (c) 2019 Chris Ferdinandi
5 | * MIT License
6 | * http://github.com/cferdinandi/gumshoe
7 | */
8 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/matrix_gather.rst:
--------------------------------------------------------------------------------
1 | Matrix gather
2 | =============
3 |
4 | Demonstrates gathering of a distributed matrix as it may used in domain partitioning applications.
5 |
6 | .. literalinclude:: ../../../examples/matrix_gather.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/blocking.rst.txt:
--------------------------------------------------------------------------------
1 | Blocking send and receive
2 | =========================
3 |
4 | Demonstrates various blocking send and receive modes of standard data types.
5 |
6 | .. literalinclude:: ../../../examples/blocking.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/hello_world.rst:
--------------------------------------------------------------------------------
1 | Hello world
2 | ===========
3 |
4 | Simple hello-world program. Initializes the message passing environment and determines the number of processes and rank.
5 |
6 | .. literalinclude:: ../../../examples/hello_world.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/matrix_gather.rst.txt:
--------------------------------------------------------------------------------
1 | Matrix gather
2 | =============
3 |
4 | Demonstrates gathering of a distributed matrix as it may used in domain partitioning applications.
5 |
6 | .. literalinclude:: ../../../examples/matrix_gather.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/mpl/message.hpp:
--------------------------------------------------------------------------------
1 | #if !(defined MPL_MESSAGE_HPP)
2 |
3 | #define MPL_MESSAGE_HPP
4 |
5 | #include
6 |
7 |
8 | namespace mpl {
9 |
10 | /// Status of a received message.
11 | using message_t = MPI_Message;
12 |
13 | } // namespace mpl
14 |
15 | #endif
16 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/blocking_vector.rst:
--------------------------------------------------------------------------------
1 | Blocking send and receive of vectors
2 | ====================================
3 |
4 | Demonstrates blocking send and receive of a vector of standard data types.
5 |
6 | .. literalinclude:: ../../../examples/blocking_vector.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/hello_world.rst.txt:
--------------------------------------------------------------------------------
1 | Hello world
2 | ===========
3 |
4 | Simple hello-world program. Initializes the message passing environment and determines the number of processes and rank.
5 |
6 | .. literalinclude:: ../../../examples/hello_world.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/blocking_vector.rst.txt:
--------------------------------------------------------------------------------
1 | Blocking send and receive of vectors
2 | ====================================
3 |
4 | Demonstrates blocking send and receive of a vector of standard data types.
5 |
6 | .. literalinclude:: ../../../examples/blocking_vector.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/nonblocking_mult.rst:
--------------------------------------------------------------------------------
1 | Gather via non-blocking send and receive
2 | ========================================
3 |
4 | Utilizes non-blocking send and receive of standard data types to implement a gather operation.
5 |
6 | .. literalinclude:: ../../../examples/nonblocking_mult.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/distributed_grid_scatter_gather.rst:
--------------------------------------------------------------------------------
1 | Distributed grid collective operations
2 | ======================================
3 |
4 | Scatter and gather operations with data type ``mpl::distributed_grid``.
5 |
6 | .. literalinclude:: ../../../examples/distributed_grid_scatter_gather.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/nonblocking.rst:
--------------------------------------------------------------------------------
1 | Non-blocking send and receive
2 | =============================
3 |
4 | Demonstrates non-blocking send and receive of standard data types and vectors of standard data types and different waiting methods.
5 |
6 | .. literalinclude:: ../../../examples/nonblocking.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/distributed_grid_scatter_gather.rst.txt:
--------------------------------------------------------------------------------
1 | Distributed grid collective operations
2 | ======================================
3 |
4 | Scatter and gather operations with data type ``mpl::distributed_grid``.
5 |
6 | .. literalinclude:: ../../../examples/distributed_grid_scatter_gather.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/nonblocking_mult.rst.txt:
--------------------------------------------------------------------------------
1 | Gather via non-blocking send and receive
2 | ========================================
3 |
4 | Utilizes non-blocking send and receive of standard data types to implement a gather operation.
5 |
6 | .. literalinclude:: ../../../examples/nonblocking_mult.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/nonblocking.rst.txt:
--------------------------------------------------------------------------------
1 | Non-blocking send and receive
2 | =============================
3 |
4 | Demonstrates non-blocking send and receive of standard data types and vectors of standard data types and different waiting methods.
5 |
6 | .. literalinclude:: ../../../examples/nonblocking.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/doc/sphinx/constants.rst:
--------------------------------------------------------------------------------
1 | Constants
2 | =========
3 |
4 | MPL defines the following global constants:
5 |
6 | .. doxygenvariable:: mpl::proc_null
7 |
8 | .. doxygenvariable:: mpl::undefined
9 |
10 | .. doxygenvariable:: mpl::root
11 |
12 | .. doxygenvariable:: mpl::absolute
13 |
14 | .. doxygenvariable:: mpl::bsend_overhead
15 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/arrays.rst:
--------------------------------------------------------------------------------
1 | Arrays
2 | ======
3 |
4 | Sends and receives arrays (C arrays and ``std::array``) of fixed size, which must be known at compile time. The types of the array elements must be suited for communication. These rules may be applied recursively.
5 |
6 | .. literalinclude:: ../../../examples/arrays.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/constants.rst.txt:
--------------------------------------------------------------------------------
1 | Constants
2 | =========
3 |
4 | MPL defines the following global constants:
5 |
6 | .. doxygenvariable:: mpl::proc_null
7 |
8 | .. doxygenvariable:: mpl::undefined
9 |
10 | .. doxygenvariable:: mpl::root
11 |
12 | .. doxygenvariable:: mpl::absolute
13 |
14 | .. doxygenvariable:: mpl::bsend_overhead
15 |
--------------------------------------------------------------------------------
/docs/html/_static/check-solid.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/arrays.rst.txt:
--------------------------------------------------------------------------------
1 | Arrays
2 | ======
3 |
4 | Sends and receives arrays (C arrays and ``std::array``) of fixed size, which must be known at compile time. The types of the array elements must be suited for communication. These rules may be applied recursively.
5 |
6 | .. literalinclude:: ../../../examples/arrays.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/parallel_sort.rst:
--------------------------------------------------------------------------------
1 | Parallel sorting
2 | ================
3 |
4 | Parallel sort algorithm, MPI version.
5 |
6 | .. literalinclude:: ../../../examples/parallel_sort_mpi.c
7 | :language: c
8 |
9 |
10 | Parallel sort algorithm, MPL version.
11 |
12 | .. literalinclude:: ../../../examples/parallel_sort_mpl.cc
13 | :language: c++
14 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/parallel_sort.rst.txt:
--------------------------------------------------------------------------------
1 | Parallel sorting
2 | ================
3 |
4 | Parallel sort algorithm, MPI version.
5 |
6 | .. literalinclude:: ../../../examples/parallel_sort_mpi.c
7 | :language: c
8 |
9 |
10 | Parallel sort algorithm, MPL version.
11 |
12 | .. literalinclude:: ../../../examples/parallel_sort_mpl.cc
13 | :language: c++
14 |
--------------------------------------------------------------------------------
/doc/sphinx/file_error_handling.cc:
--------------------------------------------------------------------------------
1 | try {
2 | mpl::file file;
3 | file.open(comm_world, "file_name.bin",
4 | mpl::file::access_mode::create | mpl::file::access_mode::read_write);
5 | // further file operations
6 | file.close();
7 | } catch (mpl::io_failure &error) {
8 | // catch and handle i/o failures
9 | std::cerr << error.what() << '\n';
10 | }
11 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/heat_equation_Jacobi_method.rst:
--------------------------------------------------------------------------------
1 | Heat equation Jacobi solver
2 | ===========================
3 |
4 | Solves the two-dimensional time-independent heat equation with fixed temperatures at the border via Jacobi iterations. Implementation uses ``mpl::distributed_grid``.
5 |
6 | .. literalinclude:: ../../../examples/heat_equation_Jacobi_method.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/heat_equation_Jacobi_method.rst.txt:
--------------------------------------------------------------------------------
1 | Heat equation Jacobi solver
2 | ===========================
3 |
4 | Solves the two-dimensional time-independent heat equation with fixed temperatures at the border via Jacobi iterations. Implementation uses ``mpl::distributed_grid``.
5 |
6 | .. literalinclude:: ../../../examples/heat_equation_Jacobi_method.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-610b9e33bc07bb04b4607643a1f9f6ac5fc1da80.png.map:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-75a1f18eb87795bf7a08712374e54c8d1b2bd278.png.map:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-ac4fbb3880ee103a7ca5c201fb2dee5b4a532839.png.map:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-b4b2d9f87128e4daea95a129e33a37e63efa7c98.png.map:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-684df2bb1f5f269b07d535b765e98e0faed34052.png.map:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-7106b06e7ffc5ab56026f5ac8ff442871e53c310.png.map:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/docs/html/_images/graphviz-b254f1bb6c2aa092534cd14c8d6efccda1b3235f.png.map:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/reduce.rst:
--------------------------------------------------------------------------------
1 | Reduction operations
2 | =====================
3 |
4 | Demonstrates use of custom reduction functions.
5 |
6 | .. literalinclude:: ../../../examples/reduce_lcm.cc
7 | :language: c++
8 |
9 |
10 | Demonstrates use of reduction functions for std::pair to determine a minimum as its location.
11 |
12 | .. literalinclude:: ../../../examples/reduce_min_loc.cc
13 | :language: c++
14 |
--------------------------------------------------------------------------------
/docs/html/_static/documentation_options.js:
--------------------------------------------------------------------------------
1 | const DOCUMENTATION_OPTIONS = {
2 | VERSION: '0.4.0',
3 | LANGUAGE: 'en',
4 | COLLAPSE_INDEX: false,
5 | BUILDER: 'html',
6 | FILE_SUFFIX: '.html',
7 | LINK_SUFFIX: '.html',
8 | HAS_SOURCE: true,
9 | SOURCELINK_SUFFIX: '.txt',
10 | NAVIGATION_WITH_KEYS: true,
11 | SHOW_SEARCH_SUMMARY: true,
12 | ENABLE_SEARCH_SHORTCUTS: true,
13 | };
--------------------------------------------------------------------------------
/doc/sphinx/examples/struct.rst:
--------------------------------------------------------------------------------
1 | Using structs
2 | =============
3 |
4 | Demonstrates how to use ``class mpl::struct_builder`` to enable communication using structures and classes. Class members must be of fixed size (no dynamic memory allocation). All types of the class members must be suited for communication. These rules may be applied recursively.
5 |
6 | .. literalinclude:: ../../../examples/struct.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/reduce.rst.txt:
--------------------------------------------------------------------------------
1 | Reduction operations
2 | =====================
3 |
4 | Demonstrates use of custom reduction functions.
5 |
6 | .. literalinclude:: ../../../examples/reduce_lcm.cc
7 | :language: c++
8 |
9 |
10 | Demonstrates use of reduction functions for std::pair to determine a minimum as its location.
11 |
12 | .. literalinclude:: ../../../examples/reduce_min_loc.cc
13 | :language: c++
14 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/struct.rst.txt:
--------------------------------------------------------------------------------
1 | Using structs
2 | =============
3 |
4 | Demonstrates how to use ``class mpl::struct_builder`` to enable communication using structures and classes. Class members must be of fixed size (no dynamic memory allocation). All types of the class members must be suited for communication. These rules may be applied recursively.
5 |
6 | .. literalinclude:: ../../../examples/struct.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/heat_equation_successive_over-relaxation.rst:
--------------------------------------------------------------------------------
1 | Heat equation successive over-relaxation
2 | ========================================
3 |
4 | Solves the two-dimensional time-independent heat equation with fixed temperatures at the border via successive over-relaxation. Implementation uses ``mpl::distributed_grid``.
5 |
6 | .. literalinclude:: ../../../examples/heat_equation_successive_over-relaxation.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/test/test_displacements.cc:
--------------------------------------------------------------------------------
1 | #define BOOST_TEST_MODULE displacements
2 |
3 | #include
4 | #include
5 |
6 |
7 | BOOST_AUTO_TEST_CASE(displacements) {
8 | mpl::displacements displacements_1(10);
9 | mpl::displacements displacements_2{1, 2, 3};
10 | displacements_2.push_back(10);
11 | BOOST_TEST(displacements_1.size() == 10);
12 | BOOST_TEST(displacements_2.size() == 4);
13 | }
14 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/vibrating_string.rst:
--------------------------------------------------------------------------------
1 | Vibrating string
2 | ================
3 |
4 | Solves the one-dimensional wave equation via finite differences, MPI version.
5 |
6 | .. literalinclude:: ../../../examples/vibrating_string_mpi.c
7 | :language: c
8 |
9 |
10 | Solves the one-dimensional wave equation via finite differences, MPL version.
11 |
12 | .. literalinclude:: ../../../examples/vibrating_string_mpl.cc
13 | :language: c++
14 |
--------------------------------------------------------------------------------
/doc/sphinx/tags.rst:
--------------------------------------------------------------------------------
1 | Tags
2 | ====
3 |
4 | Overview
5 | --------
6 |
7 | A integer-valued message tag must be specified in some communication operations. The class ``mpl::tag_t`` wraps such tag into a custom class. This tag can be used by the program to distinguish different types of messages.
8 |
9 |
10 | Class documentation
11 | -------------------
12 |
13 | .. doxygenclass:: mpl::tag_t
14 |
15 | .. doxygenvariable:: mpl::any_source
16 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/heat_equation_successive_over-relaxation.rst.txt:
--------------------------------------------------------------------------------
1 | Heat equation successive over-relaxation
2 | ========================================
3 |
4 | Solves the two-dimensional time-independent heat equation with fixed temperatures at the border via successive over-relaxation. Implementation uses ``mpl::distributed_grid``.
5 |
6 | .. literalinclude:: ../../../examples/heat_equation_successive_over-relaxation.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_static/copy-button.svg:
--------------------------------------------------------------------------------
1 |
6 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/vibrating_string.rst.txt:
--------------------------------------------------------------------------------
1 | Vibrating string
2 | ================
3 |
4 | Solves the one-dimensional wave equation via finite differences, MPI version.
5 |
6 | .. literalinclude:: ../../../examples/vibrating_string_mpi.c
7 | :language: c
8 |
9 |
10 | Solves the one-dimensional wave equation via finite differences, MPL version.
11 |
12 | .. literalinclude:: ../../../examples/vibrating_string_mpl.cc
13 | :language: c++
14 |
--------------------------------------------------------------------------------
/docs/html/_sources/tags.rst.txt:
--------------------------------------------------------------------------------
1 | Tags
2 | ====
3 |
4 | Overview
5 | --------
6 |
7 | A integer-valued message tag must be specified in some communication operations. The class ``mpl::tag_t`` wraps such tag into a custom class. This tag can be used by the program to distinguish different types of messages.
8 |
9 |
10 | Class documentation
11 | -------------------
12 |
13 | .. doxygenclass:: mpl::tag_t
14 |
15 | .. doxygenvariable:: mpl::any_source
16 |
--------------------------------------------------------------------------------
/doc/sphinx/_static/custom.css:
--------------------------------------------------------------------------------
1 | dl.function {
2 | margin-bottom: 1.25em;
3 | }
4 |
5 | p.breathe-sectiondef-title.rubric {
6 | font-size: x-large;
7 | font-weight: bolder;
8 | line-height: inherit;
9 | text-transform: none;
10 | }
11 |
12 | dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list > dt {
13 | font-size: var(--font-size--normal);
14 | font-weight: bolder;
15 | text-transform: none
16 | }
17 |
--------------------------------------------------------------------------------
/docs/html/_static/custom.css:
--------------------------------------------------------------------------------
1 | dl.function {
2 | margin-bottom: 1.25em;
3 | }
4 |
5 | p.breathe-sectiondef-title.rubric {
6 | font-size: x-large;
7 | font-weight: bolder;
8 | line-height: inherit;
9 | text-transform: none;
10 | }
11 |
12 | dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .field-list > dt {
13 | font-size: var(--font-size--normal);
14 | font-weight: bolder;
15 | text-transform: none
16 | }
17 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/custom_initialization.rst:
--------------------------------------------------------------------------------
1 | Custom initialization of the MPI environment
2 | ============================================
3 |
4 | MPL initializes the MPI environment automatically internally. This example program shows how to write a custom MPI initializer when more control over the initialization of the MPI environment is needed. This can be useful, when combining MPL with other MPI-based libraries.
5 |
6 | .. literalinclude:: ../../../examples/custom_initialization.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/doc/sphinx/group.rst:
--------------------------------------------------------------------------------
1 | Group
2 | =====
3 |
4 | Overview
5 | --------
6 |
7 | A group is an ordered set of process identifiers. Each process in a group is associated with an integer rank. Ranks are contiguous and start from zero. Groups are represented by ``mpl::group`` objects. A group is used within a communicator to describe the participants in a communication “universe” and to rank such participants.
8 |
9 |
10 | Class documentation
11 | -------------------
12 |
13 | .. doxygenclass:: mpl::group
14 |
--------------------------------------------------------------------------------
/docs/html/_sources/group.rst.txt:
--------------------------------------------------------------------------------
1 | Group
2 | =====
3 |
4 | Overview
5 | --------
6 |
7 | A group is an ordered set of process identifiers. Each process in a group is associated with an integer rank. Ranks are contiguous and start from zero. Groups are represented by ``mpl::group`` objects. A group is used within a communicator to describe the participants in a communication “universe” and to rank such participants.
8 |
9 |
10 | Class documentation
11 | -------------------
12 |
13 | .. doxygenclass:: mpl::group
14 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/custom_initialization.rst.txt:
--------------------------------------------------------------------------------
1 | Custom initialization of the MPI environment
2 | ============================================
3 |
4 | MPL initializes the MPI environment automatically internally. This example program shows how to write a custom MPI initializer when more control over the initialization of the MPI environment is needed. This can be useful, when combining MPL with other MPI-based libraries.
5 |
6 | .. literalinclude:: ../../../examples/custom_initialization.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/iterators.rst:
--------------------------------------------------------------------------------
1 | Iterators
2 | =========
3 |
4 | Sends and receives containers (``std::vector``, ``std::list``, etc.) given by their iterators. The types of the array elements must be suited for communication. On the receiving side, there must be sufficient preallocated memory, i.e., sending and receiving containers must be of the same size. Furthermore, tracking the address of a dereferenced iterator must result a non-const pointer on the receiving side.
5 |
6 | .. literalinclude:: ../../../examples/iterators.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/iterators.rst.txt:
--------------------------------------------------------------------------------
1 | Iterators
2 | =========
3 |
4 | Sends and receives containers (``std::vector``, ``std::list``, etc.) given by their iterators. The types of the array elements must be suited for communication. On the receiving side, there must be sufficient preallocated memory, i.e., sending and receiving containers must be of the same size. Furthermore, tracking the address of a dereferenced iterator must result a non-const pointer on the receiving side.
5 |
6 | .. literalinclude:: ../../../examples/iterators.cc
7 | :language: c++
8 |
--------------------------------------------------------------------------------
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | BasedOnStyle: Google
3 | AccessModifierOffset: -2
4 | AllowShortBlocksOnASingleLine: false
5 | AllowShortCaseLabelsOnASingleLine: false
6 | AllowShortFunctionsOnASingleLine: false
7 | AllowShortIfStatementsOnASingleLine: false
8 | AllowShortLoopsOnASingleLine: false
9 | ColumnLimit: 96
10 | MaxEmptyLinesToKeep: 2
11 | NamespaceIndentation: All
12 | RequiresClausePosition: OwnLine
13 | IndentRequiresClause: false
14 | SpaceAfterTemplateKeyword: false
15 | SortIncludes: false
16 | SortUsingDeclarations: false
17 | CommentPragmas: '^/'
18 | Standard: c++20
19 | ...
20 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/process_creation.rst:
--------------------------------------------------------------------------------
1 | Process creation
2 | ================
3 |
4 | The following two programs illustrate dynamic creation of new processes and establishing a communication channel in the form of inter-communicator.
5 |
6 | .. literalinclude:: ../../../examples/process_creation.cc
7 | :language: c++
8 |
9 | .. literalinclude:: ../../../examples/process_creation_multiple.cc
10 | :language: c++
11 |
12 |
13 | The corresponding source of the spawned process is given as shown below:
14 |
15 | .. literalinclude:: ../../../examples/process_creation_client.cc
16 | :language: c++
17 |
--------------------------------------------------------------------------------
/doc/sphinx/error.rst:
--------------------------------------------------------------------------------
1 | Error handling
2 | ==============
3 |
4 | MPL performs some consistency checks when the macro ``MPL_DEBUG`` has been defined. In case of an error, an exception may be thrown with an object having one of the following types.
5 |
6 | .. doxygenclass:: mpl::error
7 | .. doxygenclass:: mpl::invalid_rank
8 | .. doxygenclass:: mpl::invalid_tag
9 | .. doxygenclass:: mpl::invalid_size
10 | .. doxygenclass:: mpl::invalid_count
11 | .. doxygenclass:: mpl::invalid_layout
12 | .. doxygenclass:: mpl::invalid_dim
13 | .. doxygenclass:: mpl::invalid_datatype_bound
14 | .. doxygenclass:: mpl::invalid_argument
15 |
--------------------------------------------------------------------------------
/doc/sphinx/info.rst:
--------------------------------------------------------------------------------
1 | Info objects
2 | ============
3 |
4 | Overview
5 | --------
6 |
7 | Info objects store key-value pairs of string type. The semantics of these key-value pairs is defined by the MPI standard and by the employed MPI implementation. See the MPI standard and the documentation of your MPI implementation for details. Info objects are used by some MPL to pass the key-value pairs to the underlying MPI implementation to improve performance or resource utilization.
8 |
9 |
10 | Class documentation
11 | -------------------
12 |
13 | .. doxygenclass:: mpl::info
14 |
15 | .. doxygenclass:: mpl::infos
16 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/process_creation.rst.txt:
--------------------------------------------------------------------------------
1 | Process creation
2 | ================
3 |
4 | The following two programs illustrate dynamic creation of new processes and establishing a communication channel in the form of inter-communicator.
5 |
6 | .. literalinclude:: ../../../examples/process_creation.cc
7 | :language: c++
8 |
9 | .. literalinclude:: ../../../examples/process_creation_multiple.cc
10 | :language: c++
11 |
12 |
13 | The corresponding source of the spawned process is given as shown below:
14 |
15 | .. literalinclude:: ../../../examples/process_creation_client.cc
16 | :language: c++
17 |
--------------------------------------------------------------------------------
/doc/sphinx/grid.rst:
--------------------------------------------------------------------------------
1 | Grids
2 | =====
3 |
4 | Global and local grids are two data structures included into MPL to facilitate the implementation of domain decomposition mathods on regular rectangular multidimensional grids. See sections :doc:`examples/distributed_grid`, :doc:`examples/distributed_grid_scatter_gather`, :doc:`examples/heat_equation_Jacobi_method` and :doc:`examples/heat_equation_successive_over-relaxation` for examples.
5 |
6 |
7 | Distributed grids
8 | -----------------
9 |
10 | .. doxygenclass:: mpl::distributed_grid
11 |
12 |
13 | Local grids
14 | -----------
15 |
16 | .. doxygenclass:: mpl::local_grid
17 |
--------------------------------------------------------------------------------
/docs/html/_sources/info.rst.txt:
--------------------------------------------------------------------------------
1 | Info objects
2 | ============
3 |
4 | Overview
5 | --------
6 |
7 | Info objects store key-value pairs of string type. The semantics of these key-value pairs is defined by the MPI standard and by the employed MPI implementation. See the MPI standard and the documentation of your MPI implementation for details. Info objects are used by some MPL to pass the key-value pairs to the underlying MPI implementation to improve performance or resource utilization.
8 |
9 |
10 | Class documentation
11 | -------------------
12 |
13 | .. doxygenclass:: mpl::info
14 |
15 | .. doxygenclass:: mpl::infos
16 |
--------------------------------------------------------------------------------
/docs/html/_sources/error.rst.txt:
--------------------------------------------------------------------------------
1 | Error handling
2 | ==============
3 |
4 | MPL performs some consistency checks when the macro ``MPL_DEBUG`` has been defined. In case of an error, an exception may be thrown with an object having one of the following types.
5 |
6 | .. doxygenclass:: mpl::error
7 | .. doxygenclass:: mpl::invalid_rank
8 | .. doxygenclass:: mpl::invalid_tag
9 | .. doxygenclass:: mpl::invalid_size
10 | .. doxygenclass:: mpl::invalid_count
11 | .. doxygenclass:: mpl::invalid_layout
12 | .. doxygenclass:: mpl::invalid_dim
13 | .. doxygenclass:: mpl::invalid_datatype_bound
14 | .. doxygenclass:: mpl::invalid_argument
15 |
--------------------------------------------------------------------------------
/docs/html/_sources/grid.rst.txt:
--------------------------------------------------------------------------------
1 | Grids
2 | =====
3 |
4 | Global and local grids are two data structures included into MPL to facilitate the implementation of domain decomposition mathods on regular rectangular multidimensional grids. See sections :doc:`examples/distributed_grid`, :doc:`examples/distributed_grid_scatter_gather`, :doc:`examples/heat_equation_Jacobi_method` and :doc:`examples/heat_equation_successive_over-relaxation` for examples.
5 |
6 |
7 | Distributed grids
8 | -----------------
9 |
10 | .. doxygenclass:: mpl::distributed_grid
11 |
12 |
13 | Local grids
14 | -----------
15 |
16 | .. doxygenclass:: mpl::local_grid
17 |
--------------------------------------------------------------------------------
/test/test_communicator_barrier.cc:
--------------------------------------------------------------------------------
1 | #define BOOST_TEST_MODULE communicator_barrier
2 |
3 | #include
4 | #include
5 |
6 |
7 | bool barrier_test() {
8 | const mpl::communicator &comm_world = mpl::environment::comm_world();
9 | comm_world.barrier();
10 | return true;
11 | }
12 |
13 |
14 | bool ibarrier_test() {
15 | const mpl::communicator &comm_world = mpl::environment::comm_world();
16 | auto r{comm_world.ibarrier()};
17 | r.wait();
18 | return true;
19 | }
20 |
21 |
22 | BOOST_AUTO_TEST_CASE(barrier) {
23 | BOOST_TEST(barrier_test());
24 | BOOST_TEST(ibarrier_test());
25 | }
26 |
--------------------------------------------------------------------------------
/doc/sphinx/examples/index.rst:
--------------------------------------------------------------------------------
1 | Examples
2 | ========
3 |
4 | .. toctree::
5 |
6 | hello_world
7 | standard_types
8 | struct
9 | arrays
10 | stl_container
11 | iterators
12 | blocking
13 | blocking_vector
14 | nonblocking
15 | nonblocking_mult
16 | probe
17 | communicator
18 | collective
19 | gather
20 | gatherv
21 | matrix_gather
22 | reduce
23 | layouts
24 | subarray
25 | custom_initialization
26 | parallel_sort
27 | vibrating_string
28 | distributed_grid
29 | distributed_grid_scatter_gather
30 | heat_equation_Jacobi_method
31 | heat_equation_successive_over-relaxation
32 | process_creation
33 | file
34 |
--------------------------------------------------------------------------------
/docs/html/_sources/examples/index.rst.txt:
--------------------------------------------------------------------------------
1 | Examples
2 | ========
3 |
4 | .. toctree::
5 |
6 | hello_world
7 | standard_types
8 | struct
9 | arrays
10 | stl_container
11 | iterators
12 | blocking
13 | blocking_vector
14 | nonblocking
15 | nonblocking_mult
16 | probe
17 | communicator
18 | collective
19 | gather
20 | gatherv
21 | matrix_gather
22 | reduce
23 | layouts
24 | subarray
25 | custom_initialization
26 | parallel_sort
27 | vibrating_string
28 | distributed_grid
29 | distributed_grid_scatter_gather
30 | heat_equation_Jacobi_method
31 | heat_equation_successive_over-relaxation
32 | process_creation
33 | file
34 |
--------------------------------------------------------------------------------
/test/test_info.cc:
--------------------------------------------------------------------------------
1 | #define BOOST_TEST_MODULE info
2 |
3 | #include
4 | #include
5 |
6 |
7 | BOOST_AUTO_TEST_CASE(info) {
8 | [[maybe_unused]] const mpl::communicator &comm_world{mpl::environment::comm_world()};
9 |
10 | mpl::info info_1;
11 | BOOST_TEST(info_1.size() == 0);
12 | info_1.set("Douglas Adams", "The Hitchhiker's Guide to the Galaxy");
13 | info_1.set("Isaac Asimov", "Nightfall");
14 | BOOST_TEST(info_1.size() == 2);
15 | BOOST_TEST(info_1.value("Isaac Asimov").value() == "Nightfall");
16 |
17 | mpl::info info_2{info_1};
18 | BOOST_TEST(info_1.size() == 2);
19 | BOOST_TEST(info_2.value("Isaac Asimov").value() == "Nightfall");
20 |
21 | BOOST_TEST(not info_2.value("no such thing"));
22 | }
23 |
--------------------------------------------------------------------------------
/examples/process_creation.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | // include MPL header file
4 | #include
5 |
6 |
7 | int main() {
8 | using namespace std::string_literals;
9 | // get a reference to communicator "world"
10 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
11 | // spawn 2 new processes
12 | mpl::info info;
13 | info.set("host", "localhost");
14 | auto inter_comm{comm_world.spawn(0, 2, {"./process_creation_client"s}, info)};
15 | // broadcast a message to the created processes
16 | double message;
17 | if (comm_world.rank() == 0) {
18 | // root rank
19 | message = 1.23;
20 | inter_comm.bcast(mpl::root, message);
21 | } else
22 | // non-root ranks
23 | inter_comm.bcast(mpl::proc_null, message);
24 |
25 | return EXIT_SUCCESS;
26 | }
27 |
--------------------------------------------------------------------------------
/examples/nonblocking_mult.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 |
7 | int main() {
8 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
9 | double x{1.23456 + comm_world.rank()};
10 | mpl::irequest r_send(comm_world.isend(x, 0)); // nonblocking send to rank 0
11 | // rank 0 receives data from all ranks
12 | if (comm_world.rank() == 0) {
13 | std::vector v(comm_world.size());
14 | mpl::irequest_pool r_pool;
15 | for (int i{0}; i < comm_world.size(); ++i)
16 | r_pool.push(comm_world.irecv(v[i], i));
17 | r_pool.waitall(); // wait to finish all receive operations
18 | for (int i{0}; i < comm_world.size(); ++i)
19 | std::cout << i << '\t' << v[i] << '\n';
20 | }
21 | r_send.wait(); // wait to finish send operation
22 | return EXIT_SUCCESS;
23 | }
24 |
--------------------------------------------------------------------------------
/.github/workflows/build-with-mpich.yml:
--------------------------------------------------------------------------------
1 | name: build-with-mpich
2 | run-name: Build MPL with MPICH
3 | on: [push, pull_request, workflow_dispatch]
4 | jobs:
5 | compile-mpl:
6 | runs-on: ubuntu-22.04
7 | steps:
8 | - name: Check out repository code
9 | uses: actions/checkout@v4
10 | - name: Install build dependencies
11 | run: |
12 | sudo apt install libmpich-dev cmake ninja-build g++ libboost-test-dev
13 | mpichversion
14 | - name: Build mpl
15 | run: |
16 | mkdir build
17 | cd build
18 | cmake -G Ninja -DCMAKE_INSTALL_PREFIX="$HOME/mpl" -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -DMPL_BUILD_EXAMPLES=ON ..
19 | cmake --build . -j
20 | cmake --build . --target install
21 | - name: Test mpl
22 | run: |
23 | cd build
24 | ctest --output-on-failure
25 | - run: echo "This job's status is ${{ job.status }}."
26 |
--------------------------------------------------------------------------------
/.github/workflows/build-with-openmpi.yml:
--------------------------------------------------------------------------------
1 | name: build-with-openmpi
2 | run-name: Build MPL with OpenMPI
3 | on: [push, pull_request, workflow_dispatch]
4 | jobs:
5 | compile-mpl:
6 | runs-on: ubuntu-24.04
7 | steps:
8 | - name: Check out repository code
9 | uses: actions/checkout@v4
10 | - name: Install build dependencies
11 | run: |
12 | sudo apt install libopenmpi-dev cmake ninja-build g++ libboost-test-dev
13 | ompi_info
14 | - name: Build mpl
15 | run: |
16 | mkdir build
17 | cd build
18 | cmake -G Ninja -DCMAKE_INSTALL_PREFIX="$HOME/mpl" -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -DMPL_BUILD_EXAMPLES=ON ..
19 | cmake --build . -j
20 | cmake --build . --target install
21 | - name: Test mpl
22 | run: |
23 | cd build
24 | ctest --output-on-failure
25 | - run: echo "This job's status is ${{ job.status }}."
26 |
--------------------------------------------------------------------------------
/examples/process_creation_client.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | // include MPL header file
4 | #include
5 |
6 |
7 | int main(int argc, char *argv[]) {
8 | using namespace std::string_literals;
9 |
10 | // get a reference to communicator "world"
11 | [[maybe_unused]] const mpl::communicator &comm_world{mpl::environment::comm_world()};
12 | // get the parent inter-communicator
13 | auto &inter_comm{mpl::inter_communicator::parent()};
14 | std::cout << "Hello world! I am running on \"" << mpl::environment::processor_name()
15 | << "\". My rank is " << inter_comm.rank() << " out of " << inter_comm.size()
16 | << " processes.\n";
17 | std::cout << "commandline arguments: ";
18 | for (int i{0}; i < argc; ++i)
19 | std::cout << argv[i] << ' ';
20 | std::cout << std::endl;
21 | double message;
22 | inter_comm.bcast(0, message);
23 | std::cout << "got: " << message << '\n';
24 | return EXIT_SUCCESS;
25 | }
26 |
--------------------------------------------------------------------------------
/examples/process_creation_multiple.cc:
--------------------------------------------------------------------------------
1 | #include
2 | // include MPL header file
3 | #include
4 |
5 |
6 | int main() {
7 | using namespace std::string_literals;
8 | // get a reference to communicator "world"
9 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
10 | // spawn 2 new processes
11 | mpl::info info;
12 | info.set("host", "localhost");
13 | auto inter_comm{
14 | comm_world.spawn_multiple(0,
15 | {{"./process_creation_client"s, "arg1"s},
16 | {"./process_creation_client"s, "arg1"s, "arg2"s},
17 | {"./process_creation_client"s, "arg1"s, "arg2"s, "arg3"s}},
18 | {info, info, info})};
19 | // broadcast a message to the created processes
20 | double message;
21 | if (comm_world.rank() == 0) {
22 | // root rank
23 | message = 1.23;
24 | inter_comm.bcast(mpl::root, message);
25 | } else
26 | // non-root ranks
27 | inter_comm.bcast(mpl::proc_null, message);
28 |
29 | return EXIT_SUCCESS;
30 | }
31 |
--------------------------------------------------------------------------------
/test/test_communicator_allgather.cc:
--------------------------------------------------------------------------------
1 | #define BOOST_TEST_MODULE communicator_allgather
2 |
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 |
10 | template
11 | bool allgather_test(const T &val) {
12 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
13 | std::vector v(comm_world.size());
14 | comm_world.allgather(val, v.data());
15 | return std::all_of(v.begin(), v.end(), [&val](const auto &x) { return x == val; });
16 | }
17 |
18 |
19 | template
20 | bool iallgather_test(const T &val) {
21 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
22 | std::vector v(comm_world.size());
23 | auto r{comm_world.iallgather(val, v.data())};
24 | r.wait();
25 | return std::all_of(v.begin(), v.end(), [&val](const auto &x) { return x == val; });
26 | }
27 |
28 |
29 | BOOST_AUTO_TEST_CASE(allgather) {
30 | BOOST_TEST(allgather_test(1.0));
31 | BOOST_TEST(allgather_test(std::array{1, 2, 3, 4}));
32 |
33 | BOOST_TEST(iallgather_test(1.0));
34 | BOOST_TEST(iallgather_test(std::array{1, 2, 3, 4}));
35 | }
36 |
--------------------------------------------------------------------------------
/doc/sphinx/environmental_management.rst:
--------------------------------------------------------------------------------
1 | Environmental management
2 | ========================
3 |
4 | MPL provides various functions for querying characteristics of the computational environment.
5 |
6 |
7 | Current processor name
8 | ----------------------
9 |
10 | .. doxygenfunction:: mpl::environment::processor_name
11 |
12 |
13 | Predefined communicators
14 | ------------------------
15 |
16 | .. doxygenfunction:: mpl::environment::comm_world
17 | .. doxygenfunction:: mpl::environment::comm_self
18 |
19 |
20 | Threading support
21 | -----------------
22 |
23 | .. doxygenfunction:: mpl::environment::is_thread_main
24 | .. doxygenfunction:: mpl::environment::threading_mode
25 | .. doxygenenum:: mpl::threading_modes
26 |
27 |
28 | Time
29 | ----
30 |
31 | .. doxygenfunction:: mpl::environment::wtime_is_global
32 | .. doxygenfunction:: mpl::environment::wtime
33 | .. doxygenfunction:: mpl::environment::wtick
34 |
35 |
36 | Management of buffers for buffered send operations
37 | --------------------------------------------------
38 |
39 | .. doxygenfunction:: mpl::environment::buffer_attach
40 | .. doxygenfunction:: mpl::environment::buffer_detach
41 | .. doxygenclass:: mpl::bsend_buffer
42 |
--------------------------------------------------------------------------------
/docs/html/_sources/environmental_management.rst.txt:
--------------------------------------------------------------------------------
1 | Environmental management
2 | ========================
3 |
4 | MPL provides various functions for querying characteristics of the computational environment.
5 |
6 |
7 | Current processor name
8 | ----------------------
9 |
10 | .. doxygenfunction:: mpl::environment::processor_name
11 |
12 |
13 | Predefined communicators
14 | ------------------------
15 |
16 | .. doxygenfunction:: mpl::environment::comm_world
17 | .. doxygenfunction:: mpl::environment::comm_self
18 |
19 |
20 | Threading support
21 | -----------------
22 |
23 | .. doxygenfunction:: mpl::environment::is_thread_main
24 | .. doxygenfunction:: mpl::environment::threading_mode
25 | .. doxygenenum:: mpl::threading_modes
26 |
27 |
28 | Time
29 | ----
30 |
31 | .. doxygenfunction:: mpl::environment::wtime_is_global
32 | .. doxygenfunction:: mpl::environment::wtime
33 | .. doxygenfunction:: mpl::environment::wtick
34 |
35 |
36 | Management of buffers for buffered send operations
37 | --------------------------------------------------
38 |
39 | .. doxygenfunction:: mpl::environment::buffer_attach
40 | .. doxygenfunction:: mpl::environment::buffer_detach
41 | .. doxygenclass:: mpl::bsend_buffer
42 |
--------------------------------------------------------------------------------
/examples/hello_world.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | // include MPL header file
4 | #include
5 |
6 |
7 | int main() {
8 | // get a reference to communicator "world"
9 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
10 | // each process prints a message containing the processor name, the rank
11 | // in communicator world and the size of communicator world
12 | // output may depend on MPI implementation
13 | std::cout << "Hello world! I am running on \"" << mpl::environment::processor_name()
14 | << "\". My rank is " << comm_world.rank() << " out of " << comm_world.size()
15 | << " processes.\n";
16 | // if there are two or more processes send a message from process 0 to process 1
17 | if (comm_world.size() >= 2) {
18 | if (comm_world.rank() == 0) {
19 | std::string message{"Hello world!"};
20 | comm_world.send(message, 1); // send message to rank 1
21 | } else if (comm_world.rank() == 1) {
22 | std::string message;
23 | comm_world.recv(message, 0); // receive message from rank 0
24 | std::cout << "got: \"" << message << "\"\n";
25 | }
26 | }
27 | return EXIT_SUCCESS;
28 | }
29 |
--------------------------------------------------------------------------------
/test/test_dist_graph_communicator.cc:
--------------------------------------------------------------------------------
1 | #define BOOST_TEST_MODULE dist_graph_communicator
2 |
3 | #include
4 | #include
5 |
6 |
7 | bool dist_graph_communicator_test() {
8 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
9 | const int size{comm_world.size()};
10 | const int rank{comm_world.rank()};
11 | mpl::distributed_graph_communicator::neighbours_set sources;
12 | mpl::distributed_graph_communicator::neighbours_set destination;
13 | if (rank == 0) {
14 | for (int i{1}; i < size; ++i) {
15 | sources.add(i);
16 | destination.add({i, 0});
17 | }
18 | } else {
19 | sources.add(0);
20 | destination.add({0, 0});
21 | }
22 | mpl::distributed_graph_communicator comm_g(comm_world, sources, destination);
23 | if (rank == 0) {
24 | if (comm_g.in_degree() != comm_g.size() - 1)
25 | return false;
26 | if (comm_g.out_degree() != comm_g.size() - 1)
27 | return false;
28 | } else {
29 | if (comm_g.in_degree() != 1)
30 | return false;
31 | if (comm_g.out_degree() != 1)
32 | return false;
33 | }
34 | return true;
35 | }
36 |
37 |
38 | BOOST_AUTO_TEST_CASE(dist_graph_communicator) {
39 | BOOST_TEST(dist_graph_communicator_test());
40 | }
41 |
--------------------------------------------------------------------------------
/test/test_initialization.cc:
--------------------------------------------------------------------------------
1 | #define BOOST_TEST_MODULE communicator
2 |
3 | #include
4 | #include
5 |
6 |
7 | class my_mpi_environment {
8 | public:
9 | my_mpi_environment(int *argc, char ***argv) {
10 | MPI_Init(argc, argv);
11 | }
12 |
13 | ~my_mpi_environment() {
14 | MPI_Finalize();
15 | }
16 | };
17 |
18 |
19 | // test manual external initialization and finalization of the MPI environment
20 | bool initialization_test() {
21 | // Create a static my_mpi_environment object on block scope before any call to MPL. The
22 | // object will initialize the MPI environment in its constructor. The object's destructor
23 | // finalizes the MPI environment. The object will be destroyed after all MPL singletons have
24 | // been freed because static objects on block scope are destroyed in reverse order compared to
25 | // creation order.
26 | const static my_mpi_environment environment{nullptr, nullptr};
27 |
28 | // Perform some MPI operations.
29 | int size{0};
30 | MPI_Comm_size(MPI_COMM_WORLD, &size);
31 | BOOST_CHECK_GT(size, 0);
32 | // Do some MPL stuff.
33 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
34 | return comm_world.is_valid();
35 | }
36 |
37 |
38 | BOOST_AUTO_TEST_CASE(initialization) {
39 | BOOST_TEST(initialization_test());
40 | }
41 |
--------------------------------------------------------------------------------
/doc/sphinx/file.rst:
--------------------------------------------------------------------------------
1 | File
2 | ====
3 |
4 | Overview
5 | --------
6 |
7 | Parallel file operations are implemented via the ``mpl::file`` class. It offers various read and write modalities (collective and non-collective, blocking and non-blocking etc.) by closely following the MPI standard. See the `MPI standard `_ for a detailed description of the semantics of the various i/o operations.
8 |
9 |
10 | Class documentation
11 | -------------------
12 |
13 | File class
14 | ^^^^^^^^^^
15 |
16 | .. doxygenclass:: mpl::file
17 |
18 |
19 | File access mode operations
20 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
21 |
22 | .. doxygenfunction:: mpl::operator|(file::access_mode, file::access_mode)
23 | .. doxygenfunction:: mpl::operator|=(file::access_mode &, file::access_mode)
24 | .. doxygenfunction:: mpl::operator&(file::access_mode, file::access_mode)
25 | .. doxygenfunction:: mpl::operator&=(file::access_mode &, file::access_mode)
26 |
27 |
28 | Error handling
29 | ^^^^^^^^^^^^^^
30 |
31 | Methods of ``mpl::file`` class may throw an exception of the type ``mpl::io_failure`` in the case of run-time i/o failures. Thus, file operations should be wrapped into a ``try`` block and possible exceptions should be caught in a matching ``catch`` clause as demonstrated in the following example:
32 |
33 | .. literalinclude:: file_error_handling.cc
34 | :language: c++
35 |
--------------------------------------------------------------------------------
/examples/file.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | // include MPL header file
7 | #include
8 |
9 |
10 | int main() {
11 | // get a reference to communicator "world"
12 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
13 | // generate some data
14 | using value_type = std::array;
15 | std::vector vec;
16 | for (std::uint8_t i{0}; i < 16; ++i)
17 | vec.push_back(
18 | {static_cast(i + 1), static_cast(comm_world.rank() + 1)});
19 | // write data into file
20 | try {
21 | // wrap i/o operations in try-catch block, i/o operations may throw
22 | mpl::file file;
23 | // opening a file is collective over all processes within the employed communicator
24 | file.open(comm_world, "test.bin",
25 | mpl::file::access_mode::create | mpl::file::access_mode::read_write);
26 | // set file view
27 | file.set_view("native");
28 | // write data
29 | mpl::vector_layout write_layout(vec.size());
30 | file.write_at_all(vec.size() * comm_world.rank(), vec.data(), write_layout);
31 | // close file
32 | file.close();
33 | } catch (mpl::error &error) {
34 | std::cerr << error.what() << '\n';
35 | }
36 | return EXIT_SUCCESS;
37 | }
38 |
--------------------------------------------------------------------------------
/docs/html/_sources/file.rst.txt:
--------------------------------------------------------------------------------
1 | File
2 | ====
3 |
4 | Overview
5 | --------
6 |
7 | Parallel file operations are implemented via the ``mpl::file`` class. It offers various read and write modalities (collective and non-collective, blocking and non-blocking etc.) by closely following the MPI standard. See the `MPI standard `_ for a detailed description of the semantics of the various i/o operations.
8 |
9 |
10 | Class documentation
11 | -------------------
12 |
13 | File class
14 | ^^^^^^^^^^
15 |
16 | .. doxygenclass:: mpl::file
17 |
18 |
19 | File access mode operations
20 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
21 |
22 | .. doxygenfunction:: mpl::operator|(file::access_mode, file::access_mode)
23 | .. doxygenfunction:: mpl::operator|=(file::access_mode &, file::access_mode)
24 | .. doxygenfunction:: mpl::operator&(file::access_mode, file::access_mode)
25 | .. doxygenfunction:: mpl::operator&=(file::access_mode &, file::access_mode)
26 |
27 |
28 | Error handling
29 | ^^^^^^^^^^^^^^
30 |
31 | Methods of ``mpl::file`` class may throw an exception of the type ``mpl::io_failure`` in the case of run-time i/o failures. Thus, file operations should be wrapped into a ``try`` block and possible exceptions should be caught in a matching ``catch`` clause as demonstrated in the following example:
32 |
33 | .. literalinclude:: file_error_handling.cc
34 | :language: c++
35 |
--------------------------------------------------------------------------------
/examples/arrays.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 |
7 | int main() {
8 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
9 | // run the program with two or more processes
10 | if (comm_world.size() < 2)
11 | comm_world.abort(EXIT_FAILURE);
12 | // send / receive a single array
13 | {
14 | const int n{10};
15 | double arr[n];
16 | if (comm_world.rank() == 0) {
17 | std::iota(arr, arr + n, 1);
18 | comm_world.send(arr, 1);
19 | }
20 | if (comm_world.rank() == 1) {
21 | comm_world.recv(arr, 0);
22 | for (int j{0}; j < n; ++j)
23 | std::cout << "arr[" << j << "] = " << arr[j] << '\n';
24 | }
25 | }
26 | // send / receive a single two-dimensional array
27 | {
28 | const int n_0{2}, n_1{3};
29 | double arr[n_0][n_1];
30 | if (comm_world.rank() == 0) {
31 | for (int j_1{0}; j_1 < n_1; ++j_1)
32 | for (int j_0{0}; j_0 < n_0; ++j_0)
33 | arr[j_0][j_1] = (j_0 + 1) + 100 * (j_1 + 1);
34 | comm_world.send(arr, 1);
35 | }
36 | if (comm_world.rank() == 1) {
37 | comm_world.recv(arr, 0);
38 | for (int j_1{0}; j_1 < n_1; ++j_1) {
39 | for (int j_0{0}; j_0 < n_0; ++j_0)
40 | std::cout << "arr[" << j_0 << ", " << j_1 << "] = " << arr[j_0][j_1] << '\n';
41 | }
42 | }
43 | }
44 | return EXIT_SUCCESS;
45 | }
46 |
--------------------------------------------------------------------------------
/examples/gatherv.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 |
7 | int main() {
8 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
9 | const auto c_rank{comm_world.rank()};
10 | const auto c_size{comm_world.size()};
11 | // fill vector with C_rank+1 elements, each having the value C_rank+1
12 | std::vector x(c_rank + 1, c_rank + 1);
13 | mpl::contiguous_layout l(c_rank + 1);
14 | // root rank will send and receive in gather operation
15 | if (c_rank == 0) {
16 | // messages of varying size will be received
17 | // need to specify appropriate memory layouts to define how many elements
18 | // will be received and where to store them
19 | mpl::layouts ls;
20 | for (int i{0}; i < c_size; ++i)
21 | // define layout for message to be received from rank i
22 | ls.push_back(mpl::indexed_layout({{
23 | i + 1, // number of int elements
24 | (i * i + i) / 2 // position of the first element in receive buffer
25 | }}));
26 | std::vector y((c_size * c_size + c_size) / 2); // receive buffer
27 | comm_world.gatherv(0, x.data(), l, y.data(), ls); // receive data
28 | // print data
29 | for (const auto &f : y)
30 | std::cout << f << '\n';
31 | } else
32 | // non-root ranks just send
33 | comm_world.gatherv(0, x.data(), l);
34 | return EXIT_SUCCESS;
35 | }
36 |
--------------------------------------------------------------------------------
/test/test_helper.hpp:
--------------------------------------------------------------------------------
1 | #if !(defined MPL_TEST_HELPER_HPP)
2 | #define MPL_TEST_HELPER_HPP
3 |
4 | #include
5 | #include
6 |
7 |
8 | template
9 | struct has_size : std::false_type {};
10 |
11 | template
12 | struct has_size> : std::true_type {};
13 |
14 |
15 | template
16 | struct has_resize : std::false_type {};
17 |
18 | template
19 | struct has_resize> : std::true_type {};
20 |
21 |
22 | template
23 | struct has_begin_end : std::false_type {};
24 |
25 | template
26 | struct has_begin_end<
27 | T, std::void_t>>
28 | : std::true_type {};
29 |
30 |
31 | struct tuple {
32 | int a{0};
33 | double b{0};
34 | tuple &operator++() {
35 | ++a;
36 | ++b;
37 | return *this;
38 | }
39 | };
40 |
41 | inline bool operator==(const tuple &t1, const tuple &t2) {
42 | return t1.a == t2.a and t1.b == t2.b;
43 | }
44 |
45 | inline tuple operator+(const tuple &t1, const tuple &t2) {
46 | return tuple{t1.a + t2.a, t1.b + t2.b};
47 | }
48 |
49 | MPL_REFLECTION(tuple, a, b)
50 |
51 |
52 | template
53 | class add {
54 | public:
55 | T operator()(const T &a, const T &b) const {
56 | return a + b;
57 | }
58 | };
59 |
60 |
61 | enum class use_non_root_overload { no, yes };
62 |
63 | #endif // MPL_TEST_HELPER_HPP
64 |
--------------------------------------------------------------------------------
/.github/workflows/build-with-IntelMPI.yml:
--------------------------------------------------------------------------------
1 | name: build-with-IntelMPI
2 | run-name: Build MPL with IntelMPI
3 | on: [push, pull_request, workflow_dispatch]
4 | jobs:
5 | compile-mpl:
6 | runs-on: ubuntu-24.04
7 | steps:
8 | - name: Check out repository code
9 | uses: actions/checkout@v4
10 | - name: Install build dependencies
11 | run: |
12 | sudo apt install cmake ninja-build g++ libboost-test-dev
13 | wget -O- https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB | gpg --dearmor | sudo tee /usr/share/keyrings/oneapi-archive-keyring.gpg > /dev/null
14 | echo "deb [signed-by=/usr/share/keyrings/oneapi-archive-keyring.gpg] https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list
15 | sudo apt update
16 | sudo apt install intel-oneapi-mpi-devel
17 | - name: Build mpl
18 | run: |
19 | mkdir build
20 | cd build
21 | . /opt/intel/oneapi/setvars.sh
22 | cmake -G Ninja -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -DMPL_BUILD_EXAMPLES=ON ..
23 | cmake -G Ninja -DCMAKE_INSTALL_PREFIX="$HOME/mpl" -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -DMPL_BUILD_EXAMPLES=ON ..
24 | cmake --build . -j
25 | cmake --build . --target install
26 | - name: Test mpl
27 | run: |
28 | cd build
29 | . /opt/intel/oneapi/setvars.sh
30 | ctest --output-on-failure
31 | - run: echo "This job's status is ${{ job.status }}."
32 |
--------------------------------------------------------------------------------
/doc/sphinx/auxiliary.rst:
--------------------------------------------------------------------------------
1 | Auxiliary functions and classes
2 | ===============================
3 |
4 | Integer types
5 | -------------
6 |
7 | .. doxygentypedef:: mpl::size_t
8 | .. doxygentypedef:: mpl::ssize_t
9 |
10 |
11 | Ranks
12 | -----
13 |
14 | .. doxygenclass:: mpl::ranks
15 |
16 |
17 | Types for probing messages
18 | --------------------------
19 |
20 | The following types are used in the context of probing messages. See section :doc:`examples/probe` for an example.
21 |
22 | .. doxygentypedef:: mpl::message_t
23 | .. doxygenclass:: mpl::status_t
24 | .. doxygenstruct:: mpl::mprobe_status
25 |
26 |
27 | Memory displacements
28 | --------------------
29 |
30 | The ``mpl::displacements`` class is used in the context of various collective communication operations that send and/or receive an amount of data that varies over the set of participating processes.
31 |
32 | .. doxygenclass:: mpl::displacements
33 |
34 |
35 | Requests
36 | --------
37 |
38 | Test status enum
39 | ^^^^^^^^^^^^^^^^
40 |
41 | .. doxygenenum:: mpl::test_result
42 |
43 |
44 | Non-blocking communication requests
45 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46 |
47 | .. doxygenclass:: mpl::irequest
48 | .. doxygenclass:: mpl::irequest_pool
49 |
50 |
51 | Persistent communication requests
52 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
53 |
54 | .. doxygenclass:: mpl::prequest
55 | .. doxygenclass:: mpl::prequest_pool
56 |
57 |
58 | Command-line arguments
59 | ----------------------
60 |
61 | .. doxygenclass:: mpl::command_line
62 |
63 | .. doxygenclass:: mpl::command_lines
64 |
--------------------------------------------------------------------------------
/docs/html/_sources/auxiliary.rst.txt:
--------------------------------------------------------------------------------
1 | Auxiliary functions and classes
2 | ===============================
3 |
4 | Integer types
5 | -------------
6 |
7 | .. doxygentypedef:: mpl::size_t
8 | .. doxygentypedef:: mpl::ssize_t
9 |
10 |
11 | Ranks
12 | -----
13 |
14 | .. doxygenclass:: mpl::ranks
15 |
16 |
17 | Types for probing messages
18 | --------------------------
19 |
20 | The following types are used in the context of probing messages. See section :doc:`examples/probe` for an example.
21 |
22 | .. doxygentypedef:: mpl::message_t
23 | .. doxygenclass:: mpl::status_t
24 | .. doxygenstruct:: mpl::mprobe_status
25 |
26 |
27 | Memory displacements
28 | --------------------
29 |
30 | The ``mpl::displacements`` class is used in the context of various collective communication operations that send and/or receive an amount of data that varies over the set of participating processes.
31 |
32 | .. doxygenclass:: mpl::displacements
33 |
34 |
35 | Requests
36 | --------
37 |
38 | Test status enum
39 | ^^^^^^^^^^^^^^^^
40 |
41 | .. doxygenenum:: mpl::test_result
42 |
43 |
44 | Non-blocking communication requests
45 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46 |
47 | .. doxygenclass:: mpl::irequest
48 | .. doxygenclass:: mpl::irequest_pool
49 |
50 |
51 | Persistent communication requests
52 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
53 |
54 | .. doxygenclass:: mpl::prequest
55 | .. doxygenclass:: mpl::prequest_pool
56 |
57 |
58 | Command-line arguments
59 | ----------------------
60 |
61 | .. doxygenclass:: mpl::command_line
62 |
63 | .. doxygenclass:: mpl::command_lines
64 |
--------------------------------------------------------------------------------
/.clang-tidy:
--------------------------------------------------------------------------------
1 | # Generated from CLion Inspection settings
2 | ---
3 | Checks: '-*,
4 | bugprone-*,
5 | -bugprone-easily-swappable-parameters,
6 | cppcoreguidelines-*,
7 | -cppcoreguidelines-avoid-magic-numbers
8 | -cppcoreguidelines-pro-bounds-pointer-arithmetic,
9 | -cppcoreguidelines-pro-type-reinterpret-cast,
10 | hicpp-*,
11 | -hicpp-braces-around-statements,
12 | -hicpp-modernize-use-emplace,
13 | modernize-*,
14 | -modernize-use-emplace,
15 | -modernize-use-trailing-return-type,
16 | mpi-*,
17 | misc-*,
18 | -misc-confusable-identifiers,
19 | -misc-coroutine-hostile-raii,
20 | -misc-header-include-cycle,
21 | -misc-include-cleaner,
22 | -misc-no-recursion,
23 | -misc-non-private-member-variables-in-classes,
24 | openmp-use-default-none,
25 | performance-*,
26 | -performance-enum-size,
27 | portability-*,
28 | -portability-restrict-system-includes,
29 | readability-*,
30 | -readability-function-size,
31 | -readability-identifier-length,
32 | -readability-magic-numbers,
33 | -readability-suspicious-call-argument,
34 | -readability-uppercase-literal-suffix,
35 | -readability-math-missing-parentheses,
36 | -readability-avoid-nested-conditional-operator,
37 | -readability-const-return-type,
38 | -readability-braces-around-statements,
39 | -readability-avoid-return-with-void-value,
40 | -readability-avoid-unconditional-preprocessor-if,
41 | -readability-function-cognitive-complexity,
42 | -readability-identifier-naming,
43 | -*-avoid-magic-numbers,
44 | -*-uppercase-literal-suffix,
45 | -*-pro-bounds-pointer-arithmetic,
46 | -*-misplaced-const,
47 | -*-pro-bounds-constant-array-index'
48 |
--------------------------------------------------------------------------------
/examples/communicator.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 |
6 | int main() {
7 | // check communicator properties of comm_world
8 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
9 | std::cout << "comm_world rank: " << comm_world.rank() << "\tsize: " << comm_world.size()
10 | << std::endl;
11 | comm_world.barrier();
12 | // split comm_world into 3 disjoint communicators
13 | // and carry out some collective communication
14 | mpl::communicator comm_3{mpl::communicator::split, comm_world, comm_world.rank() % 3};
15 | int key;
16 | if (comm_3.rank() == 0)
17 | key = comm_world.rank() % 3;
18 | comm_3.bcast(0, key);
19 | std::cout << "comm_3 rank: " << comm_3.rank() << "\tsize: " << comm_3.size()
20 | << "\tkey: " << key << std::endl;
21 | comm_world.barrier();
22 | // split comm_world into a communicator which contains all processes
23 | // except rank 0 of comm_world and carry out some collective communication
24 | mpl::communicator comm_without_0(mpl::communicator::split, comm_world,
25 | comm_world.rank() == 0 ? mpl::undefined : 1);
26 | if (comm_world.rank() != 0) {
27 | double data{1};
28 | comm_without_0.allreduce(mpl::plus(), data);
29 | std::cout << "sum: " << data << std::endl;
30 | }
31 | comm_world.barrier();
32 | std::cout << "comm_world rank: " << comm_world.rank()
33 | << "\tcomm valid: " << (comm_without_0.is_valid() ? "yes" : "no") << std::endl;
34 | return EXIT_SUCCESS;
35 | }
36 |
--------------------------------------------------------------------------------
/docs/html/_static/debug.css:
--------------------------------------------------------------------------------
1 | /*
2 | This CSS file should be overridden by the theme authors. It's
3 | meant for debugging and developing the skeleton that this theme provides.
4 | */
5 | body {
6 | font-family: -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif,
7 | "Apple Color Emoji", "Segoe UI Emoji";
8 | background: lavender;
9 | }
10 | .sb-announcement {
11 | background: rgb(131, 131, 131);
12 | }
13 | .sb-announcement__inner {
14 | background: black;
15 | color: white;
16 | }
17 | .sb-header {
18 | background: lightskyblue;
19 | }
20 | .sb-header__inner {
21 | background: royalblue;
22 | color: white;
23 | }
24 | .sb-header-secondary {
25 | background: lightcyan;
26 | }
27 | .sb-header-secondary__inner {
28 | background: cornflowerblue;
29 | color: white;
30 | }
31 | .sb-sidebar-primary {
32 | background: lightgreen;
33 | }
34 | .sb-main {
35 | background: blanchedalmond;
36 | }
37 | .sb-main__inner {
38 | background: antiquewhite;
39 | }
40 | .sb-header-article {
41 | background: lightsteelblue;
42 | }
43 | .sb-article-container {
44 | background: snow;
45 | }
46 | .sb-article-main {
47 | background: white;
48 | }
49 | .sb-footer-article {
50 | background: lightpink;
51 | }
52 | .sb-sidebar-secondary {
53 | background: lightgoldenrodyellow;
54 | }
55 | .sb-footer-content {
56 | background: plum;
57 | }
58 | .sb-footer-content__inner {
59 | background: palevioletred;
60 | }
61 | .sb-footer {
62 | background: pink;
63 | }
64 | .sb-footer__inner {
65 | background: salmon;
66 | }
67 | .sb-article {
68 | background: white;
69 | }
70 |
--------------------------------------------------------------------------------
/examples/custom_initialization.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 |
7 | // a custom initializer
8 | class my_initializer final {
9 | private:
10 | explicit my_initializer(int *argc, char **argv[]) {
11 | // initialize MPI by calling MPI_Init or MPI_Init_thread
12 | MPI_Init(argc, argv);
13 | }
14 |
15 | ~my_initializer() {
16 | // finalize MPI
17 | MPI_Finalize();
18 | }
19 |
20 | public:
21 | static void init(int *argc, char **argv[]) {
22 | // variable must be static
23 | static const my_initializer init{argc, argv};
24 | }
25 | };
26 |
27 |
28 | int main(int argc, char *argv[]) {
29 | // custom initialization of the MPI environment before any MPL call
30 | my_initializer::init(&argc, &argv);
31 |
32 | // do some MPL operations
33 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
34 | std::cout << "Hello world! I am running on \"" << mpl::environment::processor_name()
35 | << "\". My rank is " << comm_world.rank() << " out of " << comm_world.size()
36 | << " processes.\n";
37 | if (comm_world.size() >= 2) {
38 | if (comm_world.rank() == 0) {
39 | const std::string message{"Hello world!"};
40 | comm_world.send(message, 1);
41 | } else if (comm_world.rank() == 1) {
42 | std::string message;
43 | comm_world.recv(message, 0);
44 | std::cout << "got: \"" << message << "\"\n";
45 | }
46 | }
47 |
48 | // exit the program and implicitly deinitialize MPL first and MPI afterward
49 | return EXIT_SUCCESS;
50 | }
51 |
--------------------------------------------------------------------------------
/examples/subarray.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 |
7 | int main() {
8 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
9 | // run the program with two or more processes
10 | if (comm_world.size() < 2)
11 | return EXIT_FAILURE;
12 | // test layout for a subarray
13 | // layouts on sending and receiving side may differ but must be compatible
14 | const int n_0{20}, n_1{8}; // size of two-dimensional array
15 | const int s_0{11}, s_1{3}; // size of two-dimensional subarray
16 | // process 0 sends
17 | if (comm_world.rank() == 0) {
18 | // C order matrix with two-dimensional C arrays
19 | double a[n_1][n_0];
20 | for (int i_1{0}; i_1 < n_1; ++i_1)
21 | for (int i_0{0}; i_0 < n_0; ++i_0)
22 | a[i_1][i_0] = i_0 + 0.01 * i_1;
23 | mpl::subarray_layout subarray{{
24 | {n_1, s_1, 2}, // 2nd dimension: size of array, size of subarray, start of subarray
25 | {n_0, s_0, 4} // 1st dimension: size of array, size of subarray, start of subarray
26 | }};
27 | comm_world.send(&a[0][0], subarray, 1);
28 | }
29 | // process 1 receives
30 | if (comm_world.rank() == 1) {
31 | double a[s_1][s_0];
32 | mpl::contiguous_layout array{s_0 * s_1};
33 | comm_world.recv(&a[0][0], array, 0);
34 | for (int i_1{0}; i_1 < s_1; ++i_1) {
35 | for (int i_0{0}; i_0 < s_0; ++i_0)
36 | std::cout << std::fixed << std::setprecision(2) << a[i_1][i_0] << " ";
37 | std::cout << '\n';
38 | }
39 | }
40 | return EXIT_SUCCESS;
41 | }
42 |
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 | Copyright (c) 2014-2015, Heiko Bauke
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions
6 | are met:
7 |
8 | * Redistributions of source code must retain the above copyright
9 | notice, this list of conditions and the following disclaimer.
10 |
11 | * Redistributions in binary form must reproduce the above
12 | copyright notice, this list of conditions and the following
13 | disclaimer in the documentation and/or other materials provided
14 | with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived
18 | from this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 | FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 | COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 | OF THE POSSIBILITY OF SUCH DAMAGE.
32 |
--------------------------------------------------------------------------------
/examples/intercommunicator.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 |
7 | int main() {
8 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
9 | // split communicator comm_world into two groups consisting of processes with odd and even
10 | // rank in comm_world
11 | const int world_rank{comm_world.rank()};
12 | const int my_group{world_rank % 2};
13 | mpl::communicator local_communicator{mpl::communicator::split, comm_world, my_group};
14 | const int local_leader{0};
15 | const int remote_leader{my_group == 0 ? 1 : 0};
16 | // comm_world is used as the communicator that can communicate with processes in the local
17 | // group as well as in the remote group
18 | mpl::inter_communicator icom{local_communicator, local_leader, comm_world, remote_leader};
19 | // gather data from all processes in the remote group
20 | const int send_data{world_rank}; // as an example, send rank in comm_world
21 | std::vector recv_data(icom.remote_size());
22 | // will receive a set of odd or even numbers
23 | icom.allgather(send_data, recv_data.data());
24 | // output communicator characteristics and received data
25 | std::stringstream stream;
26 | stream << "inter communicator size: " << icom.size() << ";\t"
27 | << "inter communicator rank: " << icom.rank() << ";\t"
28 | << "inter communicator remote size: " << icom.remote_size() << ";\t"
29 | << "gathered data: ";
30 | for (auto &val : recv_data)
31 | stream << val << ' ';
32 | stream << '\n';
33 | std::cout << stream.str();
34 | return EXIT_SUCCESS;
35 | }
36 |
--------------------------------------------------------------------------------
/examples/blocking.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 |
6 | int main() {
7 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
8 | // run the program with two or more processes
9 | if (comm_world.size() < 2)
10 | return EXIT_FAILURE;
11 | // process 0 sends
12 | enum class tag_enum : short { tag = 1 };
13 | if (comm_world.rank() == 0) {
14 | // see MPI Standard for the semantics of standard send, buffered send,
15 | // synchronous send and ready send
16 | double x{1.23456};
17 | comm_world.send(x, 1, tag_enum::tag); // send x to rank 1 via standard send
18 | ++x;
19 | {
20 | // create a buffer for buffered send,
21 | // memory will be freed on leaving the scope
22 | int size{comm_world.bsend_size()};
23 | mpl::bsend_buffer buff{size};
24 | comm_world.bsend(x, 1); // send x to rank 1 via buffered send
25 | }
26 | ++x;
27 | comm_world.ssend(x, 1); // send x to rank 1 via synchronous send
28 | ++x;
29 | comm_world.rsend(x, 1); // send x to rank 1 via ready send
30 | }
31 | // process 1 receives
32 | if (comm_world.rank() == 1) {
33 | double x;
34 | comm_world.recv(x, 0, tag_enum::tag); // receive x from rank 0
35 | std::cout << "x = " << x << '\n';
36 | comm_world.recv(x, 0); // receive x from rank 0
37 | std::cout << "x = " << x << '\n';
38 | comm_world.recv(x, 0); // receive x from rank 0
39 | std::cout << "x = " << x << '\n';
40 | comm_world.recv(x, 0); // receive x from rank 0
41 | std::cout << "x = " << x << '\n';
42 | }
43 | return EXIT_SUCCESS;
44 | }
45 |
--------------------------------------------------------------------------------
/examples/gather.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 |
7 | int main() {
8 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
9 | const auto c_rank{comm_world.rank()};
10 | const auto c_size{comm_world.size()};
11 | // gather a single int from all ranks to rank root=0
12 | {
13 | int root{0};
14 | int x{c_rank + 1};
15 | std::vector y(c_rank == root ? c_size : 0);
16 | comm_world.gather(root, x, y.data());
17 | if (c_rank == root) {
18 | for (int i{0}; i < c_size; ++i)
19 | std::cout << y[i] << ' ';
20 | std::cout << "\n";
21 | }
22 | }
23 | // gather a single int from all ranks to rank root=0
24 | // root and non-root rank use different function overloads of gather
25 | {
26 | const int root{0};
27 | int x{-(c_rank + 1)};
28 | if (c_rank == root) {
29 | std::vector y(c_size);
30 | comm_world.gather(root, x, y.data());
31 | for (int i{0}; i < c_size; ++i)
32 | std::cout << y[i] << ' ';
33 | std::cout << "\n";
34 | } else
35 | comm_world.gather(root, x);
36 | }
37 | // gather several ints from all ranks to rank root=0
38 | {
39 | const int root{0}, n{3};
40 | std::vector x(n, c_rank + 1);
41 | std::vector y(c_rank == root ? n * c_size : 0);
42 | mpl::contiguous_layout l(n);
43 | comm_world.gather(root, x.data(), l, y.data(), l);
44 | if (c_rank == root) {
45 | for (int i{0}; i < c_size * n; ++i)
46 | std::cout << y[i] << ' ';
47 | std::cout << "\n";
48 | }
49 | }
50 | return EXIT_SUCCESS;
51 | }
52 |
--------------------------------------------------------------------------------
/examples/iterators.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 |
11 | int main() {
12 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
13 | // run the program with two or more processes
14 | if (comm_world.size() < 2)
15 | comm_world.abort(EXIT_FAILURE);
16 | // send / receive a single vector
17 | {
18 | const int n{10};
19 | std::vector l(n);
20 | if (comm_world.rank() == 0) {
21 | std::iota(begin(l), end(l), 1);
22 | comm_world.send(begin(l), end(l), 1);
23 | }
24 | if (comm_world.rank() == 1) {
25 | comm_world.recv(begin(l), end(l), 0);
26 | std::for_each(begin(l), end(l), [](double x) { std::cout << x << '\n'; });
27 | }
28 | }
29 | // send / receive a single list
30 | {
31 | const int n{10};
32 | std::list l(n);
33 | if (comm_world.rank() == 0) {
34 | std::iota(begin(l), end(l), 1);
35 | comm_world.send(begin(l), end(l), 1);
36 | }
37 | if (comm_world.rank() == 1) {
38 | comm_world.recv(begin(l), end(l), 0);
39 | std::for_each(begin(l), end(l), [](double x) { std::cout << x << '\n'; });
40 | }
41 | }
42 | // send a set / receive an array
43 | {
44 | const int n{10};
45 | if (comm_world.rank() == 0) {
46 | std::set s;
47 | for (int i{1}; i <= n; ++i)
48 | s.insert(i);
49 | comm_world.send(s.begin(), s.end(), 1);
50 | }
51 | if (comm_world.rank() == 1) {
52 | std::array l;
53 | comm_world.recv(begin(l), end(l), 0);
54 | std::for_each(begin(l), end(l), [](double x) { std::cout << x << '\n'; });
55 | }
56 | }
57 | return EXIT_SUCCESS;
58 | }
59 |
--------------------------------------------------------------------------------
/test/test_group.cc:
--------------------------------------------------------------------------------
1 | #define BOOST_TEST_MODULE group
2 |
3 | #include
4 | #include
5 |
6 |
7 | BOOST_AUTO_TEST_CASE(group) {
8 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
9 | const mpl::communicator &comm_self{mpl::environment::comm_self()};
10 |
11 | mpl::group group_world{comm_world};
12 | mpl::group group_self{comm_self};
13 |
14 | BOOST_TEST((group_world.size() == comm_world.size()));
15 | BOOST_TEST((group_world.rank() == comm_world.rank()));
16 | BOOST_TEST((group_self.size() == comm_self.size()));
17 |
18 | mpl::group group_world_copy{group_world};
19 | BOOST_TEST((group_world == group_world_copy));
20 |
21 | if (comm_world.size() > 1)
22 | BOOST_TEST((group_world != group_self));
23 | else
24 | BOOST_TEST((group_world == group_self));
25 | if (comm_world.size() > 1)
26 | BOOST_TEST((group_world.compare(group_self) == mpl::group::unequal));
27 | else
28 | BOOST_TEST((group_world.compare(group_self) == mpl::group::identical));
29 |
30 | BOOST_TEST((group_self.translate(0, group_world) == group_world.rank()));
31 |
32 | mpl::group group_union(mpl::group::Union, group_world, group_self);
33 | mpl::group group_intersection(mpl::group::intersection, group_world, group_self);
34 | mpl::group group_difference(mpl::group::difference, group_world, group_self);
35 | mpl::group group_with_0(mpl::group::include, group_world, {0});
36 | mpl::group group_without_0(mpl::group::exclude, group_world, {0});
37 |
38 | BOOST_TEST((group_union.size() == group_world.size()));
39 | BOOST_TEST((group_intersection.size() == 1));
40 | BOOST_TEST((group_difference.size() == group_world.size() - 1));
41 | BOOST_TEST((group_with_0.size() == 1));
42 | BOOST_TEST((group_without_0.size() == group_world.size() - 1));
43 | }
44 |
--------------------------------------------------------------------------------
/doc/sphinx/cmake_integration.rst:
--------------------------------------------------------------------------------
1 | CMake integration
2 | =================
3 |
4 | MPL provides supporting files for CMake integration. These are also installed during the installation step. CMake integration is realized via the ``mpl`` CMake package, which provides the library target ``mpl::mpl``. The following example ``CMakeLists.txt`` file illustrates the usage of the ``mpl`` CMake package for creating an MPL application. First, the ``mpl`` package is loaded via the ``find_package`` function. Then, all targets with MPL dependency must be linked against ``mpl::mpl``. In this way, CMake adds all necessary compiler flags and linker flags that are required for building an MPL application.
5 |
6 | .. code-block:: CMake
7 |
8 | # MPI CMake module available since version 3.10
9 | cmake_minimum_required(VERSION 3.10)
10 |
11 | project(hello_mpl)
12 |
13 | # project requires c++17 to build
14 | set(CMAKE_CXX_STANDARD 17)
15 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
16 | set(CMAKE_CXX_EXTENSIONS OFF)
17 |
18 | # find the MPL library and its dependencies, e.g., an MPI library
19 | find_package(mpl REQUIRED)
20 |
21 | # create executable and link against mpl and its dependencies
22 | add_executable(hello_world hello_world.cc)
23 | target_link_libraries(hello_world PRIVATE mpl::mpl)
24 |
25 | When using ``find_package``, CMake searches in a set of platform-dependent standard directories for the requested CMake package. CMake may fail to find the MPL CMake package when MPL was installed in a custom directory. If MPL was installed in a custom directory, add the installation directory (given via ``CMAKE_INSTALL_PREFIX`` during MPL configuration see :ref:`Installation`) to the ``CMAKE_PREFIX_PATH`` variable during the configuration of the MPL application, e.g.:
26 |
27 | .. code:: shell
28 |
29 | user@host:~/hello_mpl/build$ cmake -DCMAKE_PREFIX_PATH:PATH=/path/to/mpl ..
30 |
--------------------------------------------------------------------------------
/docs/html/_sources/cmake_integration.rst.txt:
--------------------------------------------------------------------------------
1 | CMake integration
2 | =================
3 |
4 | MPL provides supporting files for CMake integration. These are also installed during the installation step. CMake integration is realized via the ``mpl`` CMake package, which provides the library target ``mpl::mpl``. The following example ``CMakeLists.txt`` file illustrates the usage of the ``mpl`` CMake package for creating an MPL application. First, the ``mpl`` package is loaded via the ``find_package`` function. Then, all targets with MPL dependency must be linked against ``mpl::mpl``. In this way, CMake adds all necessary compiler flags and linker flags that are required for building an MPL application.
5 |
6 | .. code-block:: CMake
7 |
8 | # MPI CMake module available since version 3.10
9 | cmake_minimum_required(VERSION 3.10)
10 |
11 | project(hello_mpl)
12 |
13 | # project requires c++17 to build
14 | set(CMAKE_CXX_STANDARD 17)
15 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
16 | set(CMAKE_CXX_EXTENSIONS OFF)
17 |
18 | # find the MPL library and its dependencies, e.g., an MPI library
19 | find_package(mpl REQUIRED)
20 |
21 | # create executable and link against mpl and its dependencies
22 | add_executable(hello_world hello_world.cc)
23 | target_link_libraries(hello_world PRIVATE mpl::mpl)
24 |
25 | When using ``find_package``, CMake searches in a set of platform-dependent standard directories for the requested CMake package. CMake may fail to find the MPL CMake package when MPL was installed in a custom directory. If MPL was installed in a custom directory, add the installation directory (given via ``CMAKE_INSTALL_PREFIX`` during MPL configuration see :ref:`Installation`) to the ``CMAKE_PREFIX_PATH`` variable during the configuration of the MPL application, e.g.:
26 |
27 | .. code:: shell
28 |
29 | user@host:~/hello_mpl/build$ cmake -DCMAKE_PREFIX_PATH:PATH=/path/to/mpl ..
30 |
--------------------------------------------------------------------------------
/examples/probe.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 |
8 | template
9 | void print_range(const char *const str, I i_1, I i_2) {
10 | std::cout << str;
11 | while (i_1 != i_2) {
12 | std::cout << (*i_1);
13 | ++i_1;
14 | std::cout << ((i_1 != i_2) ? ' ' : '\n');
15 | }
16 | }
17 |
18 |
19 | int main() {
20 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
21 | // run the program with two or more processes
22 | if (comm_world.size() < 2)
23 | return EXIT_FAILURE;
24 | if (comm_world.rank() == 0) {
25 | // send a message of n elements to rank 1
26 | enum class tag { send = 29 };
27 | const int n{12};
28 | std::vector v(n);
29 | mpl::contiguous_layout l(n);
30 | std::iota(v.begin(), v.end(), 0);
31 | comm_world.send(v.data(), l, 1, tag::send);
32 | }
33 | if (comm_world.rank() == 1) {
34 | // receive a message of an a priori unknown number of elements from rank 0
35 | // first probe for a message from some arbitrary rank with any tag
36 | mpl::status_t s(comm_world.probe(mpl::any_source, mpl::tag_t::any()));
37 | // decode the number of elements, the source and the tag
38 | const int n{s.get_count()}, source{s.source()};
39 | const mpl::tag_t tag(s.tag());
40 | std::cerr << "source : " << s.source() << '\n'
41 | << "tag : " << s.tag() << '\n'
42 | << "error : " << s.error() << '\n'
43 | << "count : " << n << '\n';
44 | // reserve sufficient amount of memory to receive the message
45 | std::vector v(n);
46 | mpl::contiguous_layout l(n);
47 | // finally, receive the message
48 | comm_world.recv(v.data(), l, source, tag);
49 | print_range("v = ", v.begin(), v.end());
50 | }
51 | return EXIT_SUCCESS;
52 | }
53 |
--------------------------------------------------------------------------------
/mpl/displacements.hpp:
--------------------------------------------------------------------------------
1 | #if !(defined MPL_DISPLACEMENTS_HPP)
2 |
3 | #define MPL_DISPLACEMENTS_HPP
4 |
5 | #include
6 | #include
7 | #include
8 |
9 |
10 | namespace mpl {
11 |
12 | /// Set of %displacements indicates the beginning of data buffers in various collective
13 | /// communication operations.
14 | /// \note Individual %displacements are always given in bytes.
15 | class displacements : private std::vector {
16 | using base = std::vector;
17 |
18 | public:
19 | using size_type = base::size_type;
20 | using value_type = base::value_type;
21 | using base::iterator;
22 | using base::const_iterator;
23 |
24 | /// Constructs a set of displacements with displacement zero.
25 | /// \param n number of displacements
26 | explicit displacements(size_type n = 0) : base(n, 0) {
27 | }
28 |
29 | /// Constructs a set of displacements with given displacements.
30 | /// \param init initial displacements
31 | explicit displacements(std::initializer_list init) : base(init) {
32 | }
33 |
34 | /// Copy constructor.
35 | /// \param other the other set of displacements to copy from
36 | displacements(const displacements &other) = default;
37 | /// Move constructor.
38 | /// \param other the other set of displacements to move from
39 | displacements(displacements &&other) = default;
40 |
41 | using base::operator=;
42 | using base::begin;
43 | using base::end;
44 | using base::cbegin;
45 | using base::cend;
46 | using base::operator[];
47 | using base::size;
48 | using base::push_back;
49 | using base::resize;
50 |
51 | /// Get raw displacement data.
52 | /// \return pointer to the array of displacements
53 | const MPI_Aint *operator()() const {
54 | return base::data();
55 | }
56 | };
57 |
58 | } // namespace mpl
59 |
60 | #endif
61 |
--------------------------------------------------------------------------------
/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # 3.21 required for PROJECT_IS_TOP_LEVEL, 3.10 required for mpi targets, 3.5 required for boost targets
2 | cmake_minimum_required(VERSION 3.21)
3 |
4 | project(mpl VERSION 0.4.0 LANGUAGES CXX C)
5 |
6 | if(NOT DEFINED CACHE{BUILD_TESTING})
7 | set(BUILD_TESTING OFF CACHE BOOL "")
8 | endif()
9 | include(CTest)
10 | include(GNUInstallDirs)
11 | include(CMakePackageConfigHelpers)
12 |
13 | # project requires c++17 to build
14 | set(CMAKE_CXX_STANDARD 17)
15 | set(CMAKE_CXX_STANDARD_REQUIRED ON)
16 | set(CMAKE_CXX_EXTENSIONS OFF)
17 |
18 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
19 |
20 | find_package(MPI 3.1 REQUIRED C CXX)
21 |
22 | add_library(mpl INTERFACE)
23 | target_include_directories(mpl
24 | INTERFACE
25 | $
26 | $)
27 |
28 | # convention for allowing use as a subdirectory
29 | add_library(mpl::mpl ALIAS mpl)
30 | target_link_libraries(mpl INTERFACE MPI::MPI_CXX)
31 |
32 | option(MPL_BUILD_EXAMPLES "build the mpl examples" ${PROJECT_IS_TOP_LEVEL})
33 | if(MPL_BUILD_EXAMPLES)
34 | add_subdirectory(examples)
35 | endif()
36 | if(BUILD_TESTING)
37 | add_subdirectory(test)
38 | endif()
39 |
40 | option(MPL_INSTALL "Generate and install MPL target" ${PROJECT_IS_TOP_LEVEL})
41 | if(MPL_INSTALL)
42 | install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/cmake/mplConfig.cmake DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/mpl)
43 |
44 | install(DIRECTORY mpl DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
45 |
46 | install(TARGETS mpl EXPORT mplTargets)
47 | export(EXPORT mplTargets
48 | NAMESPACE mpl::
49 | FILE mplTargets.cmake)
50 | install(EXPORT mplTargets
51 | DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/mpl
52 | NAMESPACE mpl::
53 | FILE mplTargets.cmake)
54 | endif()
55 |
56 | option(MPL_BUILD_DOCUMENTATION "build the mpl documentation using Doxygen and Sphinx" OFF)
57 | add_subdirectory(doc)
58 |
--------------------------------------------------------------------------------
/mpl/ranks.hpp:
--------------------------------------------------------------------------------
1 | #if !(defined MPL_RANKS_HPP)
2 |
3 | #define MPL_RANKS_HPP
4 |
5 | #include
6 | #include
7 | #include
8 |
9 |
10 | namespace mpl {
11 |
12 | /// Represents a collection of ranks.
13 | /// \see class \c group
14 | class ranks : private std::vector {
15 | using base = std::vector;
16 |
17 | public:
18 | using base::size_type;
19 | using base::value_type;
20 | using base::iterator;
21 | using base::const_iterator;
22 |
23 | /// Constructs collection of ranks with all ranks having value zero.
24 | /// \param n initial size of the collection
25 | explicit ranks(size_type n = 0) : base(n, 0) {
26 | }
27 |
28 | /// Constructs collection of ranks from a braces expression of integers.
29 | /// \param init list of initial values
30 | ranks(std::initializer_list init) : base(init) {
31 | }
32 |
33 | /// Constructs collection of ranks from another collection.
34 | /// \param other the other collection to copy from
35 | ranks(const ranks &other) = default;
36 |
37 | /// Move-constructs collection of ranks from another collection.
38 | /// \param other the other collection to move from
39 | ranks(ranks &&other) noexcept : base(std::move(other)) {
40 | }
41 |
42 | using base::operator=;
43 | using base::begin;
44 | using base::end;
45 | using base::cbegin;
46 | using base::cend;
47 | using base::operator[];
48 | using base::size;
49 | using base::push_back;
50 |
51 | /// Gives access to internal data.
52 | /// \return pointer to constant array
53 | [[nodiscard]] const int *operator()() const {
54 | return base::data();
55 | }
56 |
57 | /// Gives access to internal data.
58 | /// \return pointer to array
59 | [[nodiscard]] int *operator()() {
60 | return base::data();
61 | }
62 | };
63 |
64 | } // namespace mpl
65 |
66 | #endif
67 |
--------------------------------------------------------------------------------
/doc/sphinx/communicator.rst:
--------------------------------------------------------------------------------
1 | Communicators
2 | =============
3 |
4 | A communicator consists of a group of processed and defines a communication context that partitions the communication space. A message sent in one context cannot be received in another context. Furthermore, where permitted, collective operations are independent of pending point-to-point operations.
5 |
6 | MPL defines several kinds of communicators:
7 |
8 | - standard communicators,
9 |
10 | - communicators with a process topology (Cartesian communicators, graph communicators, distributed graph communicators) and
11 |
12 | - inter-communicators.
13 |
14 | An inter-communicator identifies two distinct groups of processes linked with a communication context.
15 |
16 |
17 | Standard communicators
18 | ----------------------
19 |
20 | .. doxygenclass:: mpl::communicator
21 |
22 |
23 | Standard communicators for MPI interoperability
24 | -----------------------------------------------
25 |
26 | .. doxygenclass:: mpl::mpi_communicator
27 |
28 |
29 | Cartesian communicators
30 | -----------------------
31 |
32 | .. doxygenclass:: mpl::cartesian_communicator
33 |
34 |
35 | Auxiliary functions and classes for cartesian communicators
36 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
37 |
38 | For constructing communicators with a cartesian process topology the following utility function can be used.
39 |
40 | .. doxygenfunction:: mpl::dims_create
41 |
42 | .. doxygenstruct:: mpl::shift_ranks
43 |
44 |
45 | Graph communicators
46 | -------------------
47 |
48 | .. doxygenclass:: mpl::graph_communicator
49 |
50 |
51 | Distributed graph communicators
52 | -------------------------------
53 |
54 | .. doxygenclass:: mpl::distributed_graph_communicator
55 |
56 |
57 | Inter-communicators
58 | -------------------
59 |
60 | .. doxygenclass:: mpl::inter_communicator
61 |
62 |
63 | Inter-communicators for MPI interoperability
64 | -----------------------------------------------
65 |
66 | .. doxygenclass:: mpl::mpi_inter_communicator
67 |
--------------------------------------------------------------------------------
/docs/html/_sources/communicator.rst.txt:
--------------------------------------------------------------------------------
1 | Communicators
2 | =============
3 |
4 | A communicator consists of a group of processed and defines a communication context that partitions the communication space. A message sent in one context cannot be received in another context. Furthermore, where permitted, collective operations are independent of pending point-to-point operations.
5 |
6 | MPL defines several kinds of communicators:
7 |
8 | - standard communicators,
9 |
10 | - communicators with a process topology (Cartesian communicators, graph communicators, distributed graph communicators) and
11 |
12 | - inter-communicators.
13 |
14 | An inter-communicator identifies two distinct groups of processes linked with a communication context.
15 |
16 |
17 | Standard communicators
18 | ----------------------
19 |
20 | .. doxygenclass:: mpl::communicator
21 |
22 |
23 | Standard communicators for MPI interoperability
24 | -----------------------------------------------
25 |
26 | .. doxygenclass:: mpl::mpi_communicator
27 |
28 |
29 | Cartesian communicators
30 | -----------------------
31 |
32 | .. doxygenclass:: mpl::cartesian_communicator
33 |
34 |
35 | Auxiliary functions and classes for cartesian communicators
36 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
37 |
38 | For constructing communicators with a cartesian process topology the following utility function can be used.
39 |
40 | .. doxygenfunction:: mpl::dims_create
41 |
42 | .. doxygenstruct:: mpl::shift_ranks
43 |
44 |
45 | Graph communicators
46 | -------------------
47 |
48 | .. doxygenclass:: mpl::graph_communicator
49 |
50 |
51 | Distributed graph communicators
52 | -------------------------------
53 |
54 | .. doxygenclass:: mpl::distributed_graph_communicator
55 |
56 |
57 | Inter-communicators
58 | -------------------
59 |
60 | .. doxygenclass:: mpl::inter_communicator
61 |
62 |
63 | Inter-communicators for MPI interoperability
64 | -----------------------------------------------
65 |
66 | .. doxygenclass:: mpl::mpi_inter_communicator
67 |
--------------------------------------------------------------------------------
/examples/reduce_min_loc.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 |
11 | // data type to store the data and the position of the global minimum
12 | using pair_t = std::pair;
13 |
14 |
15 | int main() {
16 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
17 | // generate data
18 | std::mt19937_64 g(std::time(nullptr) * comm_world.rank()); // random seed
19 | std::uniform_real_distribution<> uniform;
20 | const int n{8};
21 | // populate vector with random data
22 | std::vector v(n);
23 | std::generate(v.begin(), v.end(), [&comm_world, &g, &uniform]() {
24 | return std::make_pair(uniform(g), comm_world.rank());
25 | });
26 | // calculate minimum and its location and send result to rank root
27 | const int root{0};
28 | mpl::contiguous_layout layout(n);
29 | if (comm_world.rank() == root) {
30 | std::vector result(n);
31 | // calculate minimum
32 | comm_world.reduce(mpl::min(), root, v.data(), result.data(), layout);
33 | // display data from all ranks
34 | std::cout << "arguments:\n";
35 | for (int r{0}; r < comm_world.size(); ++r) {
36 | if (r > 0)
37 | comm_world.recv(v.data(), layout, r);
38 | for (auto i : v)
39 | std::cout << std::fixed << std::setprecision(5) << i.first << ' ' << i.second << '\t';
40 | std::cout << '\n';
41 | }
42 | // display results of global reduction
43 | std::cout << "\nresults:\n";
44 | for (const pair_t &i : result)
45 | std::cout << std::fixed << std::setprecision(5) << i.first << ' ' << i.second << '\t';
46 | std::cout << '\n';
47 | } else {
48 | // calculate minimum and its location and send result to rank 0
49 | comm_world.reduce(mpl::min(), root, v.data(), layout);
50 | // send data to rank 0 for display
51 | comm_world.send(v.data(), layout, root);
52 | }
53 | return EXIT_SUCCESS;
54 | }
55 |
--------------------------------------------------------------------------------
/test/test_graph_communicator.cc:
--------------------------------------------------------------------------------
1 | #define BOOST_TEST_MODULE graph_communicator
2 |
3 | #include
4 | #include
5 |
6 |
7 | bool graph_communicator_test() {
8 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
9 | const int size{comm_world.size()};
10 | mpl::graph_communicator::edge_set es;
11 | for (int i{1}; i < size; ++i) {
12 | es.add({0, i});
13 | es.add({i, 0});
14 | }
15 | mpl::graph_communicator comm_g(comm_world, es);
16 | if (comm_g.degree(0) != comm_g.size() - 1)
17 | return false;
18 | const auto nl_0{comm_g.neighbors(0)};
19 | if (nl_0.size() != comm_g.size() - 1)
20 | return false;
21 | const auto nl_1{comm_g.neighbors(1)};
22 | if (nl_1.size() != 1)
23 | return false;
24 | return true;
25 | }
26 |
27 |
28 | bool graph_communicator_test_2() {
29 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
30 | const int size{comm_world.size()};
31 | const int rank{comm_world.rank()};
32 | if (size >= 4) {
33 | mpl::communicator communicator_4{mpl::communicator::split, comm_world, rank < 4 ? 0 : rank};
34 | if (communicator_4.size() < 4)
35 | return true;
36 | mpl::graph_communicator::edge_set es{{0, 1}, {0, 3}, {1, 0}, {2, 3}, {3, 0}, {3, 2}};
37 | mpl::graph_communicator comm_g(communicator_4, es);
38 | if (comm_g.degree(0) != 2)
39 | return false;
40 | if (comm_g.degree(1) != 1)
41 | return false;
42 | if (comm_g.degree(2) != 1)
43 | return false;
44 | if (comm_g.degree(3) != 2)
45 | return false;
46 | if (comm_g.neighbors(0) != mpl::graph_communicator::node_list{1, 3})
47 | return false;
48 | if (comm_g.neighbors(1) != mpl::graph_communicator::node_list{0})
49 | return false;
50 | if (comm_g.neighbors(2) != mpl::graph_communicator::node_list{3})
51 | return false;
52 | if (comm_g.neighbors(3) != mpl::graph_communicator::node_list{0, 2})
53 | return false;
54 | }
55 | return true;
56 | }
57 |
58 |
59 | BOOST_AUTO_TEST_CASE(graph_communicator) {
60 | BOOST_TEST(graph_communicator_test());
61 | BOOST_TEST(graph_communicator_test_2());
62 | }
63 |
--------------------------------------------------------------------------------
/test/test_communicator_bcast.cc:
--------------------------------------------------------------------------------
1 | #define BOOST_TEST_MODULE communicator_bcast
2 |
3 | #include
4 | #include
5 |
6 |
7 | template
8 | bool bcast_test(const T &val) {
9 | const mpl::communicator &comm_world = mpl::environment::comm_world();
10 | T x{};
11 | if (comm_world.rank() == 0)
12 | x = val;
13 | comm_world.bcast(0, x);
14 | return x == val;
15 | }
16 |
17 |
18 | template
19 | bool bcast_test(const std::vector &send, const std::vector &expected,
20 | const mpl::layout &l) {
21 | const mpl::communicator &comm_world = mpl::environment::comm_world();
22 | std::vector x(send.size(), {});
23 | if (comm_world.rank() == 0)
24 | x = send;
25 | comm_world.bcast(0, x.data(), l);
26 | if (comm_world.rank() == 0)
27 | return x == send;
28 | else
29 | return x == expected;
30 | }
31 |
32 |
33 | template
34 | bool ibcast_test(const T &val) {
35 | const mpl::communicator &comm_world = mpl::environment::comm_world();
36 | T x{};
37 | if (comm_world.rank() == 0)
38 | x = val;
39 | auto r{comm_world.ibcast(0, x)};
40 | r.wait();
41 | return x == val;
42 | }
43 |
44 |
45 | template
46 | bool ibcast_test(const std::vector &send, const std::vector &expected,
47 | const mpl::layout &l) {
48 | const mpl::communicator &comm_world = mpl::environment::comm_world();
49 | std::vector x(send.size(), {});
50 | if (comm_world.rank() == 0)
51 | x = send;
52 | auto r{comm_world.ibcast(0, x.data(), l)};
53 | r.wait();
54 | if (comm_world.rank() == 0)
55 | return x == send;
56 | else
57 | return x == expected;
58 | }
59 |
60 |
61 | BOOST_AUTO_TEST_CASE(bcast) {
62 | BOOST_TEST(bcast_test(1.0));
63 | BOOST_TEST(bcast_test(std::array{1, 2, 3, 4}));
64 | BOOST_TEST(bcast_test(std::vector{1, 2, 3, 4, 5, 6}, std::vector{0, 2, 3, 0, 5, 0},
65 | mpl::indexed_layout{{{2, 1}, {1, 4}}}));
66 |
67 | BOOST_TEST(ibcast_test(1.0));
68 | BOOST_TEST(ibcast_test(std::array{1, 2, 3, 4}));
69 | BOOST_TEST(ibcast_test(std::vector{1, 2, 3, 4, 5, 6}, std::vector{0, 2, 3, 0, 5, 0},
70 | mpl::indexed_layout{{{2, 1}, {1, 4}}}));
71 | }
72 |
--------------------------------------------------------------------------------
/examples/reduce_lcm.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 |
9 |
10 | // calculate the least common multiple of two arguments
11 | template
12 | class lcm {
13 | // helper: calculate greatest common divisor
14 | T gcd(T a, T b) {
15 | constexpr T zero{};
16 | if (a < zero)
17 | a = -a;
18 | if (b < zero)
19 | b = -b;
20 | while (b > zero) {
21 | const T t{a % b};
22 | a = b;
23 | b = t;
24 | }
25 | return a;
26 | }
27 |
28 | public:
29 | T operator()(T a, T b) {
30 | constexpr T zero{};
31 | const T t{(a / gcd(a, b)) * b};
32 | if (t < zero)
33 | return -t;
34 | return t;
35 | }
36 | };
37 |
38 |
39 | int main() {
40 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
41 | // generate data
42 | std::mt19937_64 g(std::time(nullptr) * comm_world.rank()); // random seed
43 | std::uniform_int_distribution uniform{1, 12};
44 | const int n{8};
45 | // populate vector with random data
46 | std::vector v(n);
47 | std::generate(v.begin(), v.end(), [&g, &uniform]() { return uniform(g); });
48 | // calculate the least common multiple and send result to rank 0
49 | mpl::contiguous_layout layout(n);
50 | if (comm_world.rank() == 0) {
51 | std::vector result(n);
52 | // calculate the least common multiple
53 | comm_world.reduce(lcm(), 0, v.data(), result.data(), layout);
54 | // to check the result display data from all ranks
55 | std::cout << "Arguments:\n";
56 | for (int r{0}; r < comm_world.size(); ++r) {
57 | if (r > 0)
58 | comm_world.recv(v.data(), layout, r);
59 | for (auto i : v)
60 | std::cout << i << '\t';
61 | std::cout << '\n';
62 | }
63 | // display results of global reduction
64 | std::cout << "\nResults:\n";
65 | for (auto i : result)
66 | std::cout << i << '\t';
67 | std::cout << '\n';
68 | } else {
69 | // calculate the least common multiple
70 | comm_world.reduce(lcm(), 0, v.data(), layout);
71 | // send data to rank 0 for display
72 | comm_world.send(v.data(), layout, 0);
73 | }
74 | return EXIT_SUCCESS;
75 | }
76 |
--------------------------------------------------------------------------------
/mpl/mpl.hpp:
--------------------------------------------------------------------------------
1 | #if !(defined MPL_HPP)
2 |
3 | #define MPL_HPP
4 |
5 | #include
6 | #include
7 |
8 |
9 | namespace mpl {
10 |
11 | /// Wildcard value to indicate in a receive operation, e.g., \c communicator::recv, that any
12 | /// source is acceptable.
13 | /// \see \c tag_t::any
14 | constexpr int any_source = MPI_ANY_SOURCE;
15 |
16 | /// Special value that can be used instead of a rank wherever a source or a destination
17 | /// argument is required in a call to indicate that the communication shall have no effect.
18 | constexpr int proc_null = MPI_PROC_NULL;
19 |
20 | /// Special value that is used to indicate an invalid return value or function
21 | /// parameter in some functions.
22 | constexpr int undefined = MPI_UNDEFINED;
23 |
24 | /// Special value to indicate the root process in some inter-communicator collective
25 | /// operations.
26 | constexpr int root = MPI_ROOT;
27 |
28 | /// Special constant to indicate the start of the address range of message buffers.
29 | /// \anchor absolute
30 | constexpr void *absolute = MPI_BOTTOM;
31 |
32 | /// Special constant representing an upper bound on the additional space consumed when
33 | /// buffering messages.
34 | /// \see \c communicator::bsend
35 | /// \anchor bsend_overhead
36 | constexpr int bsend_overhead = MPI_BSEND_OVERHEAD;
37 |
38 | /// Unsigned integer type used for array indexing and address arithmetic.
39 | using size_t = std::size_t;
40 |
41 | /// Signed integer type used for array indexing and address arithmetic.
42 | using ssize_t = std::ptrdiff_t;
43 |
44 | } // namespace mpl
45 |
46 | #include
47 | #include
48 | #include
49 | #include
50 | #include
51 | #include
52 | #include
53 | #include
54 | #include
55 | #include
56 | #include
57 | #include
58 | #include
59 | #include
60 | #include
61 | #include
62 | #include
63 | #include
64 | #include
65 | #include
66 |
67 | #endif
68 |
--------------------------------------------------------------------------------
/docs/html/_static/copybutton.css:
--------------------------------------------------------------------------------
1 | /* Copy buttons */
2 | button.copybtn {
3 | position: absolute;
4 | display: flex;
5 | top: .3em;
6 | right: .3em;
7 | width: 1.7em;
8 | height: 1.7em;
9 | opacity: 0;
10 | transition: opacity 0.3s, border .3s, background-color .3s;
11 | user-select: none;
12 | padding: 0;
13 | border: none;
14 | outline: none;
15 | border-radius: 0.4em;
16 | /* The colors that GitHub uses */
17 | border: #1b1f2426 1px solid;
18 | background-color: #f6f8fa;
19 | color: #57606a;
20 | }
21 |
22 | button.copybtn.success {
23 | border-color: #22863a;
24 | color: #22863a;
25 | }
26 |
27 | button.copybtn svg {
28 | stroke: currentColor;
29 | width: 1.5em;
30 | height: 1.5em;
31 | padding: 0.1em;
32 | }
33 |
34 | div.highlight {
35 | position: relative;
36 | }
37 |
38 | /* Show the copybutton */
39 | .highlight:hover button.copybtn, button.copybtn.success {
40 | opacity: 1;
41 | }
42 |
43 | .highlight button.copybtn:hover {
44 | background-color: rgb(235, 235, 235);
45 | }
46 |
47 | .highlight button.copybtn:active {
48 | background-color: rgb(187, 187, 187);
49 | }
50 |
51 | /**
52 | * A minimal CSS-only tooltip copied from:
53 | * https://codepen.io/mildrenben/pen/rVBrpK
54 | *
55 | * To use, write HTML like the following:
56 | *
57 | *
Short
58 | */
59 | .o-tooltip--left {
60 | position: relative;
61 | }
62 |
63 | .o-tooltip--left:after {
64 | opacity: 0;
65 | visibility: hidden;
66 | position: absolute;
67 | content: attr(data-tooltip);
68 | padding: .2em;
69 | font-size: .8em;
70 | left: -.2em;
71 | background: grey;
72 | color: white;
73 | white-space: nowrap;
74 | z-index: 2;
75 | border-radius: 2px;
76 | transform: translateX(-102%) translateY(0);
77 | transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1);
78 | }
79 |
80 | .o-tooltip--left:hover:after {
81 | display: block;
82 | opacity: 1;
83 | visibility: visible;
84 | transform: translateX(-100%) translateY(0);
85 | transition: opacity 0.2s cubic-bezier(0.64, 0.09, 0.08, 1), transform 0.2s cubic-bezier(0.64, 0.09, 0.08, 1);
86 | transition-delay: .5s;
87 | }
88 |
89 | /* By default the copy button shouldn't show up when printing a page */
90 | @media print {
91 | button.copybtn {
92 | display: none;
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/examples/blocking_vector.cc:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 |
8 |
9 | template
10 | void print_range(const char *const str, I i_1, I i_2) {
11 | std::cout << str;
12 | while (i_1 != i_2) {
13 | std::cout << (*i_1);
14 | ++i_1;
15 | std::cout << ((i_1 != i_2) ? ' ' : '\n');
16 | }
17 | }
18 |
19 |
20 | int main() {
21 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
22 | // run the program with two or more processes
23 | if (comm_world.size() < 2)
24 | return EXIT_FAILURE;
25 | const int n{12};
26 | std::vector v(n); // vector of n elements lying contiguously in memory
27 | mpl::contiguous_layout l(n); // corresponding memory layout
28 | // process 0 sends
29 | if (comm_world.rank() == 0) {
30 | // see MPI Standard for the semantics of standard send, buffered send,
31 | // synchronous send and ready sendG
32 | std::iota(v.begin(), v.end(), 0); // fill vector with some data
33 | auto add_one{[](int x) { return x + 1; }};
34 | comm_world.send(v.data(), l, 1); // send vector to rank 1 via standard send
35 | std::transform(v.begin(), v.end(), v.begin(), add_one); // update data
36 | {
37 | // create a buffer for buffered send,
38 | // memory will be freed on leaving the scope
39 | const int size{comm_world.bsend_size(l)};
40 | mpl::bsend_buffer buff{size};
41 | comm_world.bsend(v.data(), l, 1); // send x to rank 1 via buffered send
42 | }
43 | std::transform(v.begin(), v.end(), v.begin(), add_one); // update data
44 | comm_world.ssend(v.data(), l, 1); // send x to rank 1 via synchronous send
45 | std::transform(v.begin(), v.end(), v.begin(), add_one); // update data
46 | comm_world.rsend(v.data(), l, 1); // send x to rank 1 via ready send
47 | }
48 | // process 1 receives
49 | if (comm_world.rank() == 1) {
50 | comm_world.recv(v.data(), l, 0); // receive vector from rank 0
51 | print_range("v = ", v.begin(), v.end());
52 | comm_world.recv(v.data(), l, 0); // receive vector from rank 0
53 | print_range("v = ", v.begin(), v.end());
54 | comm_world.recv(v.data(), l, 0); // receive vector from rank 0
55 | print_range("v = ", v.begin(), v.end());
56 | comm_world.recv(v.data(), l, 0); // receive vector from rank 0
57 | print_range("v = ", v.begin(), v.end());
58 | }
59 | return EXIT_SUCCESS;
60 | }
61 |
--------------------------------------------------------------------------------
/test/test_inter_communicator.cc:
--------------------------------------------------------------------------------
1 | #define BOOST_TEST_MODULE inter_communicator
2 |
3 | #include
4 | #include
5 |
6 |
7 | // test inter-communicator creation
8 | BOOST_AUTO_TEST_CASE(inter_communicator_create) {
9 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
10 | // split communicator comm_world into two groups consisting of processes with odd and even
11 | // rank in comm_world
12 | const int world_rank{comm_world.rank()};
13 | const int world_size{comm_world.size()};
14 | const int my_group{world_rank % 2};
15 | mpl::communicator local_communicator{mpl::communicator::split, comm_world, my_group};
16 | const int local_leader{0};
17 | const int remote_leader{my_group == 0 ? 1 : 0};
18 | // comm_world is used as the communicator that can communicate with processes in the local
19 | // group as well as in the remote group
20 | mpl::inter_communicator inter_com{local_communicator, local_leader, comm_world,
21 | remote_leader};
22 | BOOST_TEST((inter_com.size() + inter_com.remote_size() == world_size));
23 | if (my_group == 0) {
24 | BOOST_TEST((inter_com.size() == (world_size + 1) / 2));
25 | BOOST_TEST((inter_com.remote_size() == world_size / 2));
26 | } else {
27 | BOOST_TEST((inter_com.remote_size() == (world_size + 1) / 2));
28 | BOOST_TEST((inter_com.size() == world_size / 2));
29 | }
30 | }
31 |
32 |
33 | // test inter-communicator merge
34 | BOOST_AUTO_TEST_CASE(inter_communicator_merge) {
35 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
36 | // split communicator comm_world into two groups consisting of processes with odd and even
37 | // rank in comm_world
38 | const int world_rank{comm_world.rank()};
39 | const int my_group{world_rank % 2};
40 | mpl::communicator local_communicator{mpl::communicator::split, comm_world, my_group};
41 | const int local_leader{0};
42 | const int remote_leader{my_group == 0 ? 1 : 0};
43 | // comm_world is used as the communicator that can communicate with processes in the local
44 | // group as well as in the remote group
45 | mpl::inter_communicator inter_comm{local_communicator, local_leader, comm_world,
46 | remote_leader};
47 | mpl::communicator com{inter_comm, mpl::communicator::order_low};
48 | const auto communicator_equality{com.compare(comm_world)};
49 | BOOST_TEST((communicator_equality == mpl::communicator::congruent or
50 | communicator_equality == mpl::communicator::similar));
51 | }
52 |
--------------------------------------------------------------------------------
/doc/sphinx/design.rst:
--------------------------------------------------------------------------------
1 | .. _Design:
2 |
3 | Library design principles
4 | =========================
5 |
6 | MPL is designed on the basis of the following design principles:
7 |
8 | Resource management
9 | -------------------
10 |
11 | In a typical MPI program, a number of resources, e.g., communicators,
12 | custom data types etc., must be management. Allocation and deallocation
13 | of such resources must be done manually by explicitly calling the
14 | respective allocation and deallocation function. This is error-prone,
15 | may lead to resource leaks and requires a lot of boilerplate code.
16 |
17 | Therefore, MPL applies the principle of "resource acquisition is
18 | initialization" (RAII) and wraps all resources in custom class types.
19 | Resources are allocated in a constructor and automatically dealocated
20 | when a resource object goes out of scope by the destructor. In contrast
21 | to MPI handles, all resource classes have a value-semantics. This means,
22 | when a resource object is copies in to another one, then a new resource
23 | is created and the two resource objects manage different independent
24 | resources.
25 |
26 |
27 | Custom data types
28 | -----------------
29 |
30 | Custom data types are one of the most versatile features of MPI. With
31 | custom data types, it is possible to write very well-structured
32 | code by hiding details of the complex communication pattern in
33 | well-designed custom data types. Therefore, MPL makes it easy to
34 | create and use custom data types. These are called layouts in MPL.
35 |
36 | The size argument of MPI communication functions is usually redundant.
37 | The information that it provides can be incorporated into the
38 | data type argument with a custom data type. Therefore, MPL communication
39 | functions do not require a size argument. All information about the
40 | amount and memory layout of exchanged data is provided by data layout
41 | arguments.
42 |
43 |
44 | Avoid programming errors by strong typing
45 | -----------------------------------------
46 |
47 | It is a common error in MPI programs to pass logically inconsistent
48 | arguments to an MPI function. For example, one might pass a pointer
49 | to ``double`` as a buffer argument and pass ``MPI_FLOAT`` as the
50 | data type argument. The classic MPI api does not protect one from such
51 | kind of errors, i.e., no compiler error is caused.
52 |
53 | MPL leverages the strong type system of C++ to detect such kinds of
54 | programming mistakes at compile time, i.e., to make such programming
55 | errors impossible. For example, buffer arguments expect pointers of a
56 | specific type, rather than untyped pointers to ``void``, and MPL
57 | infers internally the right MPI data type on the basis of the pointer
58 | type.
59 |
--------------------------------------------------------------------------------
/docs/html/_sources/design.rst.txt:
--------------------------------------------------------------------------------
1 | .. _Design:
2 |
3 | Library design principles
4 | =========================
5 |
6 | MPL is designed on the basis of the following design principles:
7 |
8 | Resource management
9 | -------------------
10 |
11 | In a typical MPI program, a number of resources, e.g., communicators,
12 | custom data types etc., must be management. Allocation and deallocation
13 | of such resources must be done manually by explicitly calling the
14 | respective allocation and deallocation function. This is error-prone,
15 | may lead to resource leaks and requires a lot of boilerplate code.
16 |
17 | Therefore, MPL applies the principle of "resource acquisition is
18 | initialization" (RAII) and wraps all resources in custom class types.
19 | Resources are allocated in a constructor and automatically dealocated
20 | when a resource object goes out of scope by the destructor. In contrast
21 | to MPI handles, all resource classes have a value-semantics. This means,
22 | when a resource object is copies in to another one, then a new resource
23 | is created and the two resource objects manage different independent
24 | resources.
25 |
26 |
27 | Custom data types
28 | -----------------
29 |
30 | Custom data types are one of the most versatile features of MPI. With
31 | custom data types, it is possible to write very well-structured
32 | code by hiding details of the complex communication pattern in
33 | well-designed custom data types. Therefore, MPL makes it easy to
34 | create and use custom data types. These are called layouts in MPL.
35 |
36 | The size argument of MPI communication functions is usually redundant.
37 | The information that it provides can be incorporated into the
38 | data type argument with a custom data type. Therefore, MPL communication
39 | functions do not require a size argument. All information about the
40 | amount and memory layout of exchanged data is provided by data layout
41 | arguments.
42 |
43 |
44 | Avoid programming errors by strong typing
45 | -----------------------------------------
46 |
47 | It is a common error in MPI programs to pass logically inconsistent
48 | arguments to an MPI function. For example, one might pass a pointer
49 | to ``double`` as a buffer argument and pass ``MPI_FLOAT`` as the
50 | data type argument. The classic MPI api does not protect one from such
51 | kind of errors, i.e., no compiler error is caused.
52 |
53 | MPL leverages the strong type system of C++ to detect such kinds of
54 | programming mistakes at compile time, i.e., to make such programming
55 | errors impossible. For example, buffer arguments expect pointers of a
56 | specific type, rather than untyped pointers to ``void``, and MPL
57 | infers internally the right MPI data type on the basis of the pointer
58 | type.
59 |
--------------------------------------------------------------------------------
/mpl/vector.hpp:
--------------------------------------------------------------------------------
1 | #if !(defined MPL_VECTOR_HPP)
2 |
3 | #define MPL_VECTOR_HPP
4 |
5 | #include
6 | #include
7 |
8 |
9 | namespace mpl::detail {
10 |
11 | struct uninitialized {};
12 |
13 | template
14 | class vector {
15 | public:
16 | using value_type = T;
17 | using pointer = T *;
18 | using const_pointer = const T *;
19 | using reference = T &;
20 | using const_reference = const T &;
21 | using iterator = T *;
22 | using const_iterator = const T *;
23 | using size_type = std::size_t;
24 |
25 | private:
26 | size_type size_{0};
27 | T *data_{nullptr};
28 |
29 | public:
30 | explicit vector(size_type size)
31 | : size_{size}, data_{static_cast(operator new(size_ * sizeof(T)))} {
32 | for (size_type i{0}; i < size; ++i)
33 | new (&data_[i]) value_type();
34 | }
35 |
36 | explicit vector(size_type size, uninitialized)
37 | : size_{size},
38 | data_{static_cast(operator new(size_ * sizeof(T),
39 | std::align_val_t{alignof(T)}))} {
40 | if (not std::is_trivially_copyable::value)
41 | for (size_type i{0}; i < size; ++i)
42 | new (&data_[i]) value_type();
43 | }
44 |
45 | template
46 | explicit vector(size_type size, IterT iter)
47 | : size_{size},
48 | data_{static_cast(operator new(size_ * sizeof(T),
49 | std::align_val_t{alignof(T)}))} {
50 | for (size_type i{0}; i < size; ++i) {
51 | new (&data_[i]) value_type(*iter);
52 | ++iter;
53 | }
54 | }
55 |
56 | vector(const vector &) = delete;
57 | vector &operator=(const vector &) = delete;
58 |
59 | [[nodiscard]] size_type size() const {
60 | return size_;
61 | }
62 |
63 | [[nodiscard]] bool empty() const {
64 | return size_ == 0;
65 | }
66 |
67 | pointer data() {
68 | return data_;
69 | }
70 |
71 | const_pointer data() const {
72 | return data_;
73 | }
74 |
75 | reference operator[](size_type i) {
76 | return data_[i];
77 | }
78 | const_reference operator[](size_type i) const {
79 | return data_[i];
80 | }
81 |
82 | iterator begin() {
83 | return data_;
84 | }
85 |
86 | const_iterator begin() const {
87 | return data_;
88 | }
89 |
90 | iterator end() {
91 | return data_ + size_;
92 | }
93 |
94 | const_iterator end() const {
95 | return data_ + size_;
96 | }
97 |
98 | ~vector() {
99 | for (auto &val : *this)
100 | val.~T();
101 | operator delete(data_);
102 | }
103 | };
104 |
105 | } // namespace mpl::detail
106 |
107 | #endif // MPL_VECTOR_HPP
108 |
--------------------------------------------------------------------------------
/mpl/command_line.hpp:
--------------------------------------------------------------------------------
1 | #if !(defined MPL_COMMANDLINE_HPP)
2 |
3 | #define MPL_COMMANDLINE_HPP
4 |
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 |
11 | namespace mpl {
12 |
13 | /// Represents a set of command-line arguments.
14 | /// \see class \c communicator::spawn
15 | class command_line : private std::vector {
16 | using base = std::vector;
17 |
18 | public:
19 | using base::size_type;
20 | using base::value_type;
21 | using base::iterator;
22 | using base::const_iterator;
23 |
24 | /// Constructs an empty set of command-line arguments.
25 | explicit command_line() = default;
26 |
27 | /// Constructs set of command-line arguments from a braces expression of strings.
28 | /// \param init list of initial values
29 | command_line(std::initializer_list init) : base(init) {
30 | }
31 |
32 | /// Constructs set of command-line arguments from another set.
33 | /// \param other the other set to copy from
34 | command_line(const command_line &other) = default;
35 |
36 | /// Move-constructs set of command-line arguments from another set.
37 | /// \param other the other set to move from
38 | command_line(command_line &&other) noexcept : base(std::move(other)) {
39 | }
40 |
41 | using base::operator=;
42 | using base::begin;
43 | using base::end;
44 | using base::cbegin;
45 | using base::cend;
46 | using base::operator[];
47 | using base::size;
48 | using base::push_back;
49 | };
50 |
51 | /// Represents a list of command-line argument sets.
52 | /// \see class \c communicator::spawn_multiple
53 | class command_lines : private std::vector {
54 | using base = std::vector;
55 |
56 | public:
57 | using base::size_type;
58 | using base::value_type;
59 | using base::iterator;
60 | using base::const_iterator;
61 |
62 | /// Constructs an empty list of command-line argument sets.
63 | command_lines() = default;
64 |
65 | /// Constructs list of command-line argument sets from a braces expression of strings.
66 | /// \param init list of initial values
67 | command_lines(std::initializer_list init) : base(init) {
68 | }
69 |
70 | /// Constructs list of command-line argument sets from another list.
71 | /// \param other the other list to copy from
72 | command_lines(const command_lines &other) = default;
73 |
74 | /// Move-constructs list of command-line argument sets from another list.
75 | /// \param other the other list to move from
76 | command_lines(command_lines &&other) noexcept : base(std::move(other)) {
77 | }
78 |
79 | using base::operator=;
80 | using base::begin;
81 | using base::end;
82 | using base::cbegin;
83 | using base::cend;
84 | using base::operator[];
85 | using base::size;
86 | using base::push_back;
87 | };
88 |
89 | } // namespace mpl
90 |
91 | #endif
92 |
--------------------------------------------------------------------------------
/docs/html/_static/copybutton_funcs.js:
--------------------------------------------------------------------------------
1 | function escapeRegExp(string) {
2 | return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
3 | }
4 |
5 | /**
6 | * Removes excluded text from a Node.
7 | *
8 | * @param {Node} target Node to filter.
9 | * @param {string} exclude CSS selector of nodes to exclude.
10 | * @returns {DOMString} Text from `target` with text removed.
11 | */
12 | export function filterText(target, exclude) {
13 | const clone = target.cloneNode(true); // clone as to not modify the live DOM
14 | if (exclude) {
15 | // remove excluded nodes
16 | clone.querySelectorAll(exclude).forEach(node => node.remove());
17 | }
18 | return clone.innerText;
19 | }
20 |
21 | // Callback when a copy button is clicked. Will be passed the node that was clicked
22 | // should then grab the text and replace pieces of text that shouldn't be used in output
23 | export function formatCopyText(textContent, copybuttonPromptText, isRegexp = false, onlyCopyPromptLines = true, removePrompts = true, copyEmptyLines = true, lineContinuationChar = "", hereDocDelim = "") {
24 | var regexp;
25 | var match;
26 |
27 | // Do we check for line continuation characters and "HERE-documents"?
28 | var useLineCont = !!lineContinuationChar
29 | var useHereDoc = !!hereDocDelim
30 |
31 | // create regexp to capture prompt and remaining line
32 | if (isRegexp) {
33 | regexp = new RegExp('^(' + copybuttonPromptText + ')(.*)')
34 | } else {
35 | regexp = new RegExp('^(' + escapeRegExp(copybuttonPromptText) + ')(.*)')
36 | }
37 |
38 | const outputLines = [];
39 | var promptFound = false;
40 | var gotLineCont = false;
41 | var gotHereDoc = false;
42 | const lineGotPrompt = [];
43 | for (const line of textContent.split('\n')) {
44 | match = line.match(regexp)
45 | if (match || gotLineCont || gotHereDoc) {
46 | promptFound = regexp.test(line)
47 | lineGotPrompt.push(promptFound)
48 | if (removePrompts && promptFound) {
49 | outputLines.push(match[2])
50 | } else {
51 | outputLines.push(line)
52 | }
53 | gotLineCont = line.endsWith(lineContinuationChar) & useLineCont
54 | if (line.includes(hereDocDelim) & useHereDoc)
55 | gotHereDoc = !gotHereDoc
56 | } else if (!onlyCopyPromptLines) {
57 | outputLines.push(line)
58 | } else if (copyEmptyLines && line.trim() === '') {
59 | outputLines.push(line)
60 | }
61 | }
62 |
63 | // If no lines with the prompt were found then just use original lines
64 | if (lineGotPrompt.some(v => v === true)) {
65 | textContent = outputLines.join('\n');
66 | }
67 |
68 | // Remove a trailing newline to avoid auto-running when pasting
69 | if (textContent.endsWith("\n")) {
70 | textContent = textContent.slice(0, -1)
71 | }
72 | return textContent
73 | }
74 |
--------------------------------------------------------------------------------
/test/test_communicator_reduce_scatter.cc:
--------------------------------------------------------------------------------
1 | #define BOOST_TEST_MODULE communicator_reduce_scatter
2 |
3 | #include
4 | #include
5 | #include "test_helper.hpp"
6 |
7 |
8 | template
9 | bool reduce_scatter_test(F f, const T &val) {
10 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
11 | T x{val};
12 | std::vector v_x;
13 | mpl::contiguous_layouts l;
14 | for (int i{0}; i < comm_world.size(); ++i) {
15 | const int block_size{i + 1};
16 | for (int j{0}; j < block_size; ++j)
17 | v_x.push_back(x);
18 | l.push_back(mpl::contiguous_layout(block_size));
19 | ++x;
20 | }
21 | const int block_size{comm_world.rank() + 1};
22 | std::vector v_y(block_size);
23 | comm_world.reduce_scatter(f, v_x.data(), v_y.data(), l);
24 | x = val;
25 | for (int i{0}; i < comm_world.rank(); ++i)
26 | ++x;
27 | T expected{x};
28 | for (int i{1}; i < comm_world.size(); ++i)
29 | expected = f(expected, x);
30 | std::vector v_expected(block_size, expected);
31 | return v_y == v_expected;
32 | }
33 |
34 |
35 | template
36 | bool ireduce_scatter_test(F f, const T &val) {
37 | const mpl::communicator &comm_world{mpl::environment::comm_world()};
38 | T x{val};
39 | std::vector v_x;
40 | mpl::contiguous_layouts l;
41 | for (int i{0}; i < comm_world.size(); ++i) {
42 | const int block_size{i + 1};
43 | for (int j{0}; j < block_size; ++j)
44 | v_x.push_back(x);
45 | l.push_back(mpl::contiguous_layout(block_size));
46 | ++x;
47 | }
48 | const int block_size{comm_world.rank() + 1};
49 | std::vector v_y(block_size);
50 | auto r{comm_world.ireduce_scatter(f, v_x.data(), v_y.data(), l)};
51 | x = val;
52 | for (int i{0}; i < comm_world.rank(); ++i)
53 | ++x;
54 | T expected{x};
55 | for (int i{1}; i < comm_world.size(); ++i)
56 | expected = f(expected, x);
57 | std::vector v_expected(block_size, expected);
58 | r.wait();
59 | return v_y == v_expected;
60 | }
61 |
62 |
63 | BOOST_AUTO_TEST_CASE(reduce_scatter) {
64 | BOOST_TEST(reduce_scatter_test(add