ESPResSo
Extensible Simulation Package for Research on Soft Matter Systems
Loading...
Searching...
No Matches
gatherv.hpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2010-2022 The ESPResSo project
3 *
4 * This file is part of ESPResSo.
5 *
6 * ESPResSo is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * ESPResSo is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19#ifndef UTILS_MPI_GATHERV_HPP
20#define UTILS_MPI_GATHERV_HPP
21
22#include <boost/mpi/communicator.hpp>
23#include <boost/mpi/datatype.hpp>
24#include <boost/mpi/exception.hpp>
25#include <boost/mpi/nonblocking.hpp>
26
27#include <algorithm>
28#include <cassert>
29#include <vector>
30
31namespace Utils {
32namespace Mpi {
33
34namespace detail {
35template <typename T>
36void gatherv_impl(const boost::mpi::communicator &comm, const T *in_values,
37 int in_size, T *out_values, const int *sizes,
38 const int *displs, int root, boost::mpl::true_) {
39 if (in_values == nullptr)
40 return;
41
42 MPI_Datatype type = boost::mpi::get_mpi_datatype<T>(*in_values);
43
44 /* in-place ? */
45 if ((in_values == out_values) && (comm.rank() == root)) {
46 BOOST_MPI_CHECK_RESULT(MPI_Gatherv,
47 (MPI_IN_PLACE, 0, type, out_values,
48 const_cast<int *>(sizes), const_cast<int *>(displs),
49 type, root, comm));
50 } else {
51 BOOST_MPI_CHECK_RESULT(MPI_Gatherv,
52 (const_cast<T *>(in_values), in_size, type,
53 out_values, const_cast<int *>(sizes),
54 const_cast<int *>(displs), type, root, comm));
55 }
56}
57
58template <typename T>
59void gatherv_impl(const boost::mpi::communicator &comm, const T *in_values,
60 int in_size, T *out_values, const int *sizes,
61 const int *displs, int root, boost::mpl::false_) {
62 if (comm.rank() == root) {
63 auto const n_nodes = comm.size();
64
65 /* not in-place */
66 if (in_values && out_values && in_values != out_values) {
67 std::copy_n(in_values, in_size, out_values + displs[root]);
68 }
69
70 std::vector<boost::mpi::request> req;
71 for (int i = 0; i < n_nodes; i++) {
72 if (i == root)
73 continue;
74
75 // NOLINTNEXTLINE(clang-analyzer-core.NullDereference)
76 req.emplace_back(comm.irecv(i, 42, out_values + displs[i], sizes[i]));
77 }
78
79 boost::mpi::wait_all(req.begin(), req.end());
80 } else {
81 comm.send(root, 42, in_values, in_size);
82 }
83}
84} // namespace detail
85
86template <typename T>
87void gatherv(const boost::mpi::communicator &comm, const T *in_values,
88 int in_size, T *out_values, const int *sizes, const int *displs,
89 int root) {
90 detail::gatherv_impl(comm, in_values, in_size, out_values, sizes, displs,
92}
93
94template <typename T>
95void gatherv(const boost::mpi::communicator &comm, const T *in_values,
96 int in_size, T *out_values, const int *sizes, int root) {
97 if (comm.rank() == root) {
98 std::vector<int> displ(static_cast<unsigned int>(comm.size()));
99
100 int offset = 0;
101 for (unsigned int i = 0; i < displ.size(); i++) {
102 displ[i] = offset;
103 offset += sizes[i];
104 }
105
106 detail::gatherv_impl(comm, in_values, in_size, out_values, sizes,
107 displ.data(), root, boost::mpi::is_mpi_datatype<T>());
108
109 } else {
110 detail::gatherv_impl(comm, in_values, in_size, out_values, nullptr, nullptr,
112 }
113}
114
115template <typename T>
116void gatherv(const boost::mpi::communicator &comm, const T *in_values,
117 int in_size, int root) {
118 assert(comm.rank() != root &&
119 "This overload can not be called on the root rank.");
120 gatherv(comm, in_values, in_size, static_cast<T *>(nullptr), nullptr, nullptr,
121 root);
122}
123
124} // namespace Mpi
125} // namespace Utils
126#endif
void gatherv(const boost::mpi::communicator &comm, const T *in_values, int in_size, T *out_values, const int *sizes, const int *displs, int root)
Definition gatherv.hpp:87