43namespace nda::detail {
48 void mpi_reduce_in_place_impl(A &&a_out, mpi::communicator comm = {},
int root = 0,
bool all =
false, MPI_Op op = MPI_SUM) {
50 EXPECTS_WITH_MESSAGE(have_mpi_equal_shapes(a_out, comm),
"Error in nda::detail::mpi_reduce_in_place_impl: Shapes of arrays/views must be equal")
53 if (not mpi::has_env || comm.size() < 2) {
return; }
56 using value_type =
typename std::decay_t<A>::value_type;
57 if constexpr (not mpi::has_mpi_type<value_type>) {
59 nda::for_each(a_out.shape(), [&](
auto... args) { mpi::reduce_in_place(a_out(args...), comm, root, all, op); });
62 check_layout_mpi_compatible(a_out,
"detail::mpi_reduce_in_place_impl");
65 auto a_out_span = std::span{a_out.data(),
static_cast<std::size_t
>(a_out.size())};
66 mpi::reduce_in_place_range(a_out_span, comm, root,
all, op);
112 template <
typename A1,
typename A2>
114 void mpi_reduce_capi(A1
const &a_in, A2 &&a_out, mpi::communicator comm = {},
int root = 0,
bool all =
false, MPI_Op op = MPI_SUM) {
116 EXPECTS_WITH_MESSAGE(detail::have_mpi_equal_shapes(a_in, comm),
"Error in nda::mpi_reduce_capi: Shapes of arrays/views must be equal")
119 if (not mpi::has_env || comm.size() < 2) {
125 using value_type =
typename std::decay_t<A1>::value_type;
126 if constexpr (not mpi::has_mpi_type<value_type>) {
128 a_out =
nda::map([&](
auto const &x) {
return mpi::reduce(x, comm, root,
all, op); })(a_in);
131 detail::check_layout_mpi_compatible(a_in,
"mpi_reduce_capi");
132 if ((comm.rank() == root) ||
all) {
133 detail::check_layout_mpi_compatible(a_out,
"mpi_reduce_capi");
135 if (std::abs(a_out.data() - a_in.data()) < a_in.size()) NDA_RUNTIME_ERROR <<
"Error in nda::mpi_reduce_capi: Overlapping arrays";
139 auto a_out_span = std::span{a_out.data(),
static_cast<std::size_t
>(a_out.size())};
140 auto a_in_span = std::span{a_in.data(),
static_cast<std::size_t
>(a_in.size())};
141 mpi::reduce_range(a_in_span, a_out_span, comm, root,
all, op);
171 template <
typename A>
173 auto lazy_mpi_reduce(A &&a, mpi::communicator comm = {},
int root = 0,
bool all =
false, MPI_Op op = MPI_SUM) {
174 return mpi::lazy<mpi::tag::reduce, A>{std::forward<A>(a), comm, root,
all, op};
195 template <
typename A>
198 detail::mpi_reduce_in_place_impl(a, comm, root,
all, op);
219 template <
typename A>
221 auto mpi_reduce(A
const &a, mpi::communicator comm = {},
int root = 0,
bool all =
false, MPI_Op op = MPI_SUM) {
246template <nda::Array A>
247struct mpi::lazy<mpi::tag::reduce, A> {
264 const bool all{
false};
267 const MPI_Op op{MPI_SUM};
280 if ((comm.rank() == root) || all)
return rhs.shape();
281 return std::array<long, std::remove_cvref_t<stored_type>::rank>{};
302 template <nda::Array T>
304 if (target.data() == rhs.data()) {
305 nda::detail::mpi_reduce_in_place_impl(target, comm, root, all, op);
Provides basic functions to create and manipulate arrays and views.
Provides concepts for the nda library.
Provides various convenient aliases and helper functions for nda::basic_array and nda::basic_array_vi...
Provides a custom runtime error class and macros to assert conditions and throw exceptions.
bool all(A const &a)
Do all elements of the array evaluate to true?
void resize_or_check_if_view(A &a, std::array< long, A::rank > const &sha)
Resize a given regular array to the given shape or check if a given view as the correct shape.
mapped< F > map(F f)
Create a lazy function call expression on arrays/views.
auto lazy_mpi_reduce(A &&a, mpi::communicator comm={}, int root=0, bool all=false, MPI_Op op=MPI_SUM)
Implementation of a lazy MPI reduce for nda::basic_array or nda::basic_array_view types.
auto mpi_reduce(A const &a, mpi::communicator comm={}, int root=0, bool all=false, MPI_Op op=MPI_SUM)
Implementation of an MPI reduce for nda::basic_array or nda::basic_array_view types.
void mpi_reduce_capi(A1 const &a_in, A2 &&a_out, mpi::communicator comm={}, int root=0, bool all=false, MPI_Op op=MPI_SUM)
Implementation of an MPI reduce for nda::basic_array or nda::basic_array_view types using a C-style A...
void mpi_reduce_in_place(A &&a, mpi::communicator comm={}, int root=0, bool all=false, MPI_Op op=MPI_SUM)
Implementation of an in-place MPI reduce for nda::basic_array or nda::basic_array_view types.
decltype(basic_array{std::declval< T >()}) get_regular_t
Get the type of the nda::basic_array that would be obtained by constructing an array from a given typ...
constexpr bool is_regular_or_view_v
Constexpr variable that is true if type A is either a regular array or a view.
__inline__ void for_each(std::array< Int, R > const &shape, F &&f)
Loop over all possible index values of a given shape and apply a function to them.
Macros used in the nda library.
Provides lazy function calls on arrays/views.
Provides various utility functions used by the MPI interface of nda.
auto shape() const
Compute the shape of the nda::ArrayInitializer object.
mpi::communicator comm
MPI communicator.
stored_type rhs
Array/View to be reduced.
void invoke(T &&target) const
Execute the lazy MPI operation and write the result to a target array/view.
A stored_type
Type of the array/view stored in the lazy object.
typename std::decay_t< A >::value_type value_type
Value type of the array/view.
Provides type traits for the nda library.