Skip to content

Commit b939894

Browse files
committed
feat(mpi): add non-blocking reduce (mpi::ireduce)
Prepare for exposure in core API. Also add unit test. Signed-off-by: Gabriel Dos Santos <gabriel.dossantos@cea.fr>
1 parent 2e167dd commit b939894

3 files changed

Lines changed: 120 additions & 1 deletion

File tree

src/KokkosComm/mpi/reduce.hpp

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,68 @@
99
#include <KokkosComm/concepts.hpp>
1010
#include <KokkosComm/traits.hpp>
1111
#include <KokkosComm/datatype.hpp>
12+
#include "mpi_space.hpp"
13+
#include "req.hpp"
1214

13-
#include "impl/pack_traits.hpp"
1415
#include "impl/error_handling.hpp"
16+
#include "impl/pack_traits.hpp"
1517

1618
namespace KokkosComm::mpi {
1719

20+
template <KokkosExecutionSpace ExecSpace, KokkosView SView, KokkosView RView>
21+
auto ireduce(const ExecSpace &space, const SView sv, RView rv, MPI_Op op, int root, MPI_Comm comm) -> Req<MpiSpace> {
22+
using ST = typename SView::non_const_value_type;
23+
using RT = typename RView::non_const_value_type;
24+
using SPkr = typename PackTraits<SView>::packer_type;
25+
using RPkr = typename PackTraits<RView>::packer_type;
26+
static_assert(std::is_same_v<ST, RT>, "KokkosComm::mpi::ireduce: View value types must be identical");
27+
static_assert(rank<SView>() <= 1 and rank<RView>() <= 1,
28+
"KokkosComm::mpi::ireduce: Views with rank higher than 1 are not supported");
29+
Kokkos::Tools::pushRegion("KokkosComm::mpi::ireduce");
30+
31+
const int rank = [=]() {
32+
int _r;
33+
MPI_Comm_rank(comm, &_r);
34+
return _r;
35+
}();
36+
37+
Req<MpiSpace> req;
38+
if (is_contiguous(sv)) {
39+
if (rank == root and not is_contiguous(rv)) {
40+
auto pkd_rv = RPkr::allocate_packed_for(space, "KC::mpi::ireduce c_sv pkd_rv", rv);
41+
space.fence("fence allocation before MPI call");
42+
MPI_Ireduce(data_handle(sv), data_handle(pkd_rv.view), span(sv), datatype<MpiSpace, ST>(), op, root, comm,
43+
&req.mpi_request());
44+
RPkr::unpack_into(space, rv, pkd_rv.view);
45+
req.extend_view_lifetime(pkd_rv.view);
46+
} else {
47+
space.fence("fence before MPI call");
48+
MPI_Ireduce(data_handle(sv), data_handle(rv), span(sv), datatype<MpiSpace, ST>(), op, root, comm,
49+
&req.mpi_request());
50+
}
51+
} else {
52+
auto send_args = SPkr::pack(space, sv);
53+
if (rank == root and not is_contiguous(rv)) {
54+
auto pkd_rv = RPkr::allocate_packed_for(space, "KC::mpi::ireduce nc_sv pkd_rv", rv);
55+
space.fence("fence allocation before MPI call");
56+
MPI_Ireduce(data_handle(send_args.view), data_handle(pkd_rv.view), send_args.count, send_args.datatype, op, root,
57+
comm, &req.mpi_request());
58+
RPkr::unpack_into(space, rv, pkd_rv.view); // no-op
59+
req.extend_view_lifetime(pkd_rv.view);
60+
} else {
61+
space.fence("fence before MPI call");
62+
MPI_Ireduce(data_handle(send_args.view), data_handle(rv), send_args.count, datatype<MpiSpace, ST>(), op, root,
63+
comm, &req.mpi_request());
64+
}
65+
req.extend_view_lifetime(send_args.view);
66+
}
67+
req.extend_view_lifetime(sv);
68+
req.extend_view_lifetime(rv);
69+
70+
Kokkos::Tools::popRegion();
71+
return req;
72+
}
73+
1874
template <KokkosView SendView, KokkosView RecvView>
1975
void reduce(const SendView &sv, const RecvView &rv, MPI_Op op, int root, MPI_Comm comm) {
2076
Kokkos::Tools::pushRegion("KokkosComm::mpi::reduce");

unit_tests/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,13 @@ if(KOKKOSCOMM_ENABLE_MPI)
125125
FILES test_main.cpp mpi/test_reduce.cpp
126126
LIBRARIES KokkosComm::KokkosComm
127127
)
128+
kc_add_unit_test(
129+
test.mpi.ireduce
130+
MPI
131+
NUM_PES 2
132+
FILES test_main.cpp mpi/test_ireduce.cpp
133+
LIBRARIES KokkosComm::KokkosComm
134+
)
128135
kc_add_unit_test(
129136
test.mpi.allreduce
130137
MPI

unit_tests/mpi/test_ireduce.cpp

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
2+
// SPDX-FileCopyrightText: Copyright Contributors to the Kokkos project
3+
4+
#include <gtest/gtest.h>
5+
6+
#include <KokkosComm/KokkosComm.hpp>
7+
8+
namespace {
9+
10+
template <typename T>
11+
class NonBlockingReduce : public testing::Test {
12+
public:
13+
using Scalar = T;
14+
};
15+
16+
using ScalarTypes = ::testing::Types<int, int64_t, float, double, Kokkos::complex<float>, Kokkos::complex<double>>;
17+
TYPED_TEST_SUITE(NonBlockingReduce, ScalarTypes);
18+
19+
template <typename Scalar>
20+
void test_ireduce_1d_contig() {
21+
int rank, size;
22+
MPI_Comm_rank(MPI_COMM_WORLD, &rank);
23+
MPI_Comm_size(MPI_COMM_WORLD, &size);
24+
int root = 0;
25+
26+
Kokkos::View<Scalar *> sv("sv", 10);
27+
Kokkos::View<Scalar *> rv("rv", 10);
28+
// if (rank == root) {
29+
// Kokkos::resize(rv, sv.extent(0));
30+
// }
31+
32+
// Prepare send buffer
33+
Kokkos::parallel_for(
34+
sv.extent(0), KOKKOS_LAMBDA(int i) { sv(i) = rank + i; });
35+
36+
KokkosComm::mpi::ireduce(Kokkos::DefaultExecutionSpace(), sv, rv, MPI_SUM, root, MPI_COMM_WORLD);
37+
38+
if (root == rank) {
39+
int errs;
40+
Kokkos::parallel_reduce(
41+
rv.extent(0),
42+
KOKKOS_LAMBDA(int i, int &lsum) {
43+
Scalar acc = 0;
44+
for (int r = 0; r < size; ++r) {
45+
acc += r + i;
46+
}
47+
lsum += rv(i) != acc;
48+
},
49+
errs);
50+
ASSERT_EQ(errs, 0);
51+
}
52+
}
53+
54+
TYPED_TEST(NonBlockingReduce, 1D_contig) { test_ireduce_1d_contig<typename TestFixture::Scalar>(); }
55+
56+
} // namespace

0 commit comments

Comments
 (0)