Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

KAdventskalender: Add plugin support #444

Merged
merged 21 commits into from
Dec 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions include/kamping/collectives/allgather.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@
/// @tparam Args Automatically deducted template parameters.
/// @param args All required and any number of the optional buffers described above.
/// @return Result type wrapping the output buffer if not specified as input parameter.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
auto kamping::Communicator<DefaultContainerType>::allgather(Args... args) const {
auto kamping::Communicator<DefaultContainerType, Plugins...>::allgather(Args... args) const {
using namespace kamping::internal;
KAMPING_CHECK_PARAMETERS(Args, KAMPING_REQUIRED_PARAMETERS(send_buf), KAMPING_OPTIONAL_PARAMETERS(recv_buf));

Expand Down
4 changes: 2 additions & 2 deletions include/kamping/collectives/allreduce.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@
/// @tparam Args Automatically deducted template parameters.
/// @param args All required and any number of the optional buffers described above.
/// @return Result type wrapping the output buffer if not specified as input parameter.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
auto kamping::Communicator<DefaultContainerType>::allreduce(Args... args) const {
auto kamping::Communicator<DefaultContainerType, Plugins...>::allreduce(Args... args) const {
using namespace kamping::internal;
KAMPING_CHECK_PARAMETERS(Args, KAMPING_REQUIRED_PARAMETERS(send_buf, op), KAMPING_OPTIONAL_PARAMETERS(recv_buf));

Expand Down
8 changes: 4 additions & 4 deletions include/kamping/collectives/alltoall.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@
/// @tparam Args Automatically deducted template parameters.
/// @param args All required and any number of the optional buffers described above.
/// @return Result type wrapping the output buffer if not specified as input parameter.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
auto kamping::Communicator<DefaultContainerType>::alltoall(Args... args) const {
auto kamping::Communicator<DefaultContainerType, Plugins...>::alltoall(Args... args) const {
KAMPING_CHECK_PARAMETERS(Args, KAMPING_REQUIRED_PARAMETERS(send_buf), KAMPING_OPTIONAL_PARAMETERS(recv_buf));

auto const& send_buf = internal::select_parameter_type<internal::ParameterType::send_buf>(args...);
Expand Down Expand Up @@ -131,9 +131,9 @@ auto kamping::Communicator<DefaultContainerType>::alltoall(Args... args) const {
/// @tparam Args Automatically deducted template parameters.
/// @param args All required and any number of the optional buffers described above.
/// @return Result type wrapping the output buffer, counts and displacements if not specified as input parameter.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
auto kamping::Communicator<DefaultContainerType>::alltoallv(Args... args) const {
auto kamping::Communicator<DefaultContainerType, Plugins...>::alltoallv(Args... args) const {
// Get all parameter objects
KAMPING_CHECK_PARAMETERS(
Args,
Expand Down
4 changes: 2 additions & 2 deletions include/kamping/collectives/barrier.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@
///
/// The parameter pack prohibits the compiler form compiling this
/// function even when it's not used.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
void kamping::Communicator<DefaultContainerType>::barrier(Args... args) const {
void kamping::Communicator<DefaultContainerType, Plugins...>::barrier(Args... args) const {
using namespace kamping::internal;
static_assert(sizeof...(args) == 0, "You may not pass any arguments to barrier().");

Expand Down
8 changes: 4 additions & 4 deletions include/kamping/collectives/bcast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@
/// @tparam Args Automatically deducted template parameters.
/// @param args All required and any number of the optional buffers described above.
/// @return Result type wrapping the output buffer if not specified as input parameter.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
auto kamping::Communicator<DefaultContainerType>::bcast(Args... args) const {
auto kamping::Communicator<DefaultContainerType, Plugins...>::bcast(Args... args) const {
using namespace ::kamping::internal;
KAMPING_CHECK_PARAMETERS(
Args,
Expand Down Expand Up @@ -172,9 +172,9 @@ auto kamping::Communicator<DefaultContainerType>::bcast(Args... args) const {
/// @tparam Args Automatically deducted template parameters.
/// @param args All required and any number of the optional buffers described above.
/// @return Result type wrapping the output buffer if not specified as input parameter.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
auto kamping::Communicator<DefaultContainerType>::bcast_single(Args... args) const {
auto kamping::Communicator<DefaultContainerType, Plugins...>::bcast_single(Args... args) const {
//! If you expand this function to not being only a simple wrapper around bcast, you have to write more unit tests!

using namespace kamping::internal;
Expand Down
8 changes: 4 additions & 4 deletions include/kamping/collectives/exscan.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@
/// @tparam Args Automatically deducted template parameters.
/// @param args All required and any number of the optional buffers described above.
/// @return Result type wrapping the output buffer if not specified as input parameter.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
auto kamping::Communicator<DefaultContainerType>::exscan(Args... args) const {
auto kamping::Communicator<DefaultContainerType, Plugins...>::exscan(Args... args) const {
using namespace kamping::internal;
KAMPING_CHECK_PARAMETERS(
Args,
Expand Down Expand Up @@ -161,9 +161,9 @@ auto kamping::Communicator<DefaultContainerType>::exscan(Args... args) const {
/// @param args All required and any number of the optional buffers described above.
/// @return The single element result of the exclusive scan. A single element is returned even if \c recv_buf was a
/// vector.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
auto kamping::Communicator<DefaultContainerType>::exscan_single(Args... args) const {
auto kamping::Communicator<DefaultContainerType, Plugins...>::exscan_single(Args... args) const {
//! If you expand this function to not being only a simple wrapper around exscan, you have to write more unit
//! tests!

Expand Down
4 changes: 2 additions & 2 deletions include/kamping/collectives/gather.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@
/// @tparam Args Automatically deducted template parameters.
/// @param args All required and any number of the optional buffers described above.
/// @return Result type wrapping the output buffer if not specified as input parameter.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
auto kamping::Communicator<DefaultContainerType>::gather(Args... args) const {
auto kamping::Communicator<DefaultContainerType, Plugins...>::gather(Args... args) const {
using namespace kamping::internal;
KAMPING_CHECK_PARAMETERS(Args, KAMPING_REQUIRED_PARAMETERS(send_buf), KAMPING_OPTIONAL_PARAMETERS(recv_buf, root));

Expand Down
4 changes: 2 additions & 2 deletions include/kamping/collectives/reduce.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@
/// @tparam Args Automatically deducted template parameters.
/// @param args All required and any number of the optional buffers described above.
/// @return Result type wrapping the output buffer if not specified as input parameter.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
auto kamping::Communicator<DefaultContainerType>::reduce(Args... args) const {
auto kamping::Communicator<DefaultContainerType, Plugins...>::reduce(Args... args) const {
using namespace kamping::internal;
KAMPING_CHECK_PARAMETERS(
Args,
Expand Down
8 changes: 4 additions & 4 deletions include/kamping/collectives/scan.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,9 @@
/// @tparam Args Automatically deducted template parameters.
/// @param args All required and any number of the optional buffers described above.
/// @return Result type wrapping the output buffer if not specified as input parameter.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
auto kamping::Communicator<DefaultContainerType>::scan(Args... args) const {
auto kamping::Communicator<DefaultContainerType, Plugins...>::scan(Args... args) const {
using namespace kamping::internal;
KAMPING_CHECK_PARAMETERS(Args, KAMPING_REQUIRED_PARAMETERS(send_buf, op), KAMPING_OPTIONAL_PARAMETERS(recv_buf));

Expand Down Expand Up @@ -119,9 +119,9 @@ auto kamping::Communicator<DefaultContainerType>::scan(Args... args) const {
/// @tparam Args Automatically deducted template parameters.
/// @param args All required and any number of the optional buffers described above.
/// @return Result type wrapping the output buffer if not specified as input parameter.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
auto kamping::Communicator<DefaultContainerType>::scan_single(Args... args) const {
auto kamping::Communicator<DefaultContainerType, Plugins...>::scan_single(Args... args) const {
//! If you expand this function to not being only a simple wrapper around scan, you have to write more unit
//! tests!

Expand Down
8 changes: 4 additions & 4 deletions include/kamping/collectives/scatter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ int bcast_value(kamping::Communicator<DefaultContainerType> const& comm, T const
/// @tparam Args Deduced template parameters.
/// @param args Required and optionally optional parameters.
/// @return kamping::MPIResult wrapping the output buffer if not specified as an input parameter.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
auto kamping::Communicator<DefaultContainerType>::scatter(Args... args) const {
auto kamping::Communicator<DefaultContainerType, Plugins...>::scatter(Args... args) const {
using namespace kamping::internal;

KAMPING_CHECK_PARAMETERS(
Expand Down Expand Up @@ -206,9 +206,9 @@ auto kamping::Communicator<DefaultContainerType>::scatter(Args... args) const {
/// @tparam Args Deduced template parameters.
/// @param args Required and optionally optional parameters.
/// @return kamping::MPIResult wrapping the output buffer if not specified as an input parameter.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
auto kamping::Communicator<DefaultContainerType>::scatterv(Args... args) const {
auto kamping::Communicator<DefaultContainerType, Plugins...>::scatterv(Args... args) const {
using namespace kamping::internal;

KAMPING_CHECK_PARAMETERS(
Expand Down
4 changes: 2 additions & 2 deletions include/kamping/comm_helper/is_same_on_all_ranks.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@ namespace kamping {
/// @tparam Value Type of the value to check. Must be comparable with `operator==`.
/// @param value The value of this rank. This value is compared with the ones provided by all other ranks.
/// @return `true` if all ranks have provided the same value, `false` otherwise.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename Value>
bool Communicator<DefaultContainerType>::is_same_on_all_ranks(Value const& value) const {
bool Communicator<DefaultContainerType, Plugins...>::is_same_on_all_ranks(Value const& value) const {
// TODO Assert that two values are comparable.
// std::pair<> is not trivially_copyable and we don't want to forbid comparing std::pair<>s for equality.
/// @todo How to handle more complex data types, e.g. std::pair<>, user defined classes, std::vector (here and
Expand Down
7 changes: 5 additions & 2 deletions include/kamping/communicator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,11 @@ namespace kamping {
/// Communicator is also access point to all MPI communications provided by KaMPIng.
/// @tparam DefaultContainerType The default container type to use for containers created by KaMPIng. Defaults to
/// std::vector.
template <template <typename...> typename DefaultContainerType = std::vector>
class Communicator {
/// @tparam Plugins Plugins adding functionality to KaMPIng. Plugins should be classes taking a ``Communicator``
/// template parameter and can assume that they are castable to `Communicator` from which they can
/// call any function of `kamping::Communicator`. See `test/plugin_tests.cpp` for examples.
template <template <typename...> typename DefaultContainerType = std::vector, template <typename> typename... Plugins>
class Communicator : public Plugins<Communicator<DefaultContainerType, Plugins...>>... {
public:
/// @brief Default constructor not specifying any MPI communicator and using \c MPI_COMM_WORLD by default.
Communicator() : Communicator(MPI_COMM_WORLD) {}
Expand Down
16 changes: 8 additions & 8 deletions include/kamping/p2p/send.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@
/// - \ref kamping::send_mode() the send mode to use. Defaults to standard MPI_Send.
/// @tparam Args Automatically deducted template parameters.
/// @param args All required and any number of the optional buffers described above.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
void kamping::Communicator<DefaultContainerType>::send(Args... args) const {
void kamping::Communicator<DefaultContainerType, Plugins...>::send(Args... args) const {
using namespace kamping::internal;
KAMPING_CHECK_PARAMETERS(
Args,
Expand Down Expand Up @@ -135,24 +135,24 @@ void kamping::Communicator<DefaultContainerType>::send(Args... args) const {

/// @brief Convenience wrapper for MPI_Bsend. Calls \ref kamping::Communicator::send() with the appropriate send mode
/// set.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
void kamping::Communicator<DefaultContainerType>::bsend(Args... args) const {
void kamping::Communicator<DefaultContainerType, Plugins...>::bsend(Args... args) const {
this->send(std::forward<Args>(args)..., send_mode(send_modes::buffered));
}

/// @brief Convenience wrapper for MPI_Ssend. Calls \ref kamping::Communicator::send() with the appropriate send mode
/// set.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
void kamping::Communicator<DefaultContainerType>::ssend(Args... args) const {
void kamping::Communicator<DefaultContainerType, Plugins...>::ssend(Args... args) const {
this->send(std::forward<Args>(args)..., send_mode(send_modes::synchronous));
}

/// @brief Convenience wrapper for MPI_Rsend. Calls \ref kamping::Communicator::send() with the appropriate send mode
/// set.
template <template <typename...> typename DefaultContainerType>
template <template <typename...> typename DefaultContainerType, template <typename> typename... Plugins>
template <typename... Args>
void kamping::Communicator<DefaultContainerType>::rsend(Args... args) const {
void kamping::Communicator<DefaultContainerType, Plugins...>::rsend(Args... args) const {
this->send(std::forward<Args>(args)..., send_mode(send_modes::ready));
}
40 changes: 40 additions & 0 deletions include/kamping/plugin_helpers.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// This file is part of KaMPIng.
//
// Copyright 2022 The KaMPIng Authors
//
// KaMPIng is free software : you can redistribute it and/or modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
// version. KaMPIng is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
// for more details.
//
// You should have received a copy of the GNU Lesser General Public License along with KaMPIng. If not, see
// <https://www.gnu.org/licenses/>.

namespace kamping::plugins {

/// @brief Helper class for using CRTP for mixins. Which are used to implement kamping plugins.
///
/// Taken from https://www.fluentcpp.com/2017/05/19/crtp-helper/
/// @tparam CommunicatorClass Type of the class we want to add functionality to, i.e. `kamping::Communicator`.
Hespian marked this conversation as resolved.
Show resolved Hide resolved
/// @tparam PluginClass Type of the plugin class template which inherits from \c PluginBase and adds functionality to \c
/// CommunicatorClass.
template <typename CommunicatorClass, template <typename> class PluginClass>
struct PluginBase {
niklas-uhl marked this conversation as resolved.
Show resolved Hide resolved
private:
/// @return Reference to the underlying Communicator class.
CommunicatorClass& to_communicator() {
return static_cast<CommunicatorClass&>(*this);
}

niklas-uhl marked this conversation as resolved.
Show resolved Hide resolved
/// @return const-reference to the underlying Communicator class.
CommunicatorClass const& to_communicator() const {
return static_cast<CommunicatorClass const&>(*this);
}

PluginBase() {} ///< private constructor
friend PluginClass<CommunicatorClass>; // this allows only the class inheriting from \c PluginBase to access the
// functions of this class.
};

} // namespace kamping::plugins
5 changes: 5 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ kamping_register_mpi_test(
FILES comm_helper/mpi_communicator_is_same_on_all_ranks_test.cpp
CORES 1 4
)
kamping_register_mpi_test(
test_plugins
FILES plugins_test.cpp
CORES 1 4
)

# Tests using C++ 20
kamping_register_mpi_test(
Expand Down
Loading